mirror of
https://github.com/ChrisTitusTech/linutil.git
synced 2024-11-05 13:15:21 +00:00
Merge branch 'main' into root
This commit is contained in:
commit
7f3bfe79af
18
.github/workflows/github-pages.yml
vendored
18
.github/workflows/github-pages.yml
vendored
|
@ -13,6 +13,10 @@ on:
|
|||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
environment: linutil_env
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
|
@ -24,11 +28,17 @@ jobs:
|
|||
run: |
|
||||
echo -e "<!-- THIS FILE IS GENERATED AUTOMATICALLY. EDIT .github/CONTRIBUTING.md -->\n\n$(cat .github/CONTRIBUTING.md)" > 'docs/contributing.md'
|
||||
|
||||
- uses: stefanzweifel/git-auto-commit-action@v5
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
commit_message: Commit Contributing Guidelines
|
||||
file_pattern: "docs/contributing.md"
|
||||
add_options: '--force'
|
||||
commit-message: Update Contributing Guidelines
|
||||
title: 'docs: Update Contributing Guidelines'
|
||||
body: 'Automated update of Contributing Guidelines from .github/CONTRIBUTING.md'
|
||||
branch: update-contributing-guidelines
|
||||
delete-branch: true
|
||||
base: main
|
||||
labels: documentation
|
||||
token: ${{ secrets.PAT_TOKEN }}
|
||||
if: success()
|
||||
|
||||
- name: Setup Python
|
||||
|
|
8
.github/workflows/linutil.yml
vendored
8
.github/workflows/linutil.yml
vendored
|
@ -78,11 +78,3 @@ jobs:
|
|||
env:
|
||||
version: ${{ env.version }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linutil-artifact
|
||||
path: build/x86_64-unknown-linux-musl/release/linutil
|
||||
compression-level: 0
|
||||
overwrite: true
|
67
.github/workflows/preview.yml
vendored
67
.github/workflows/preview.yml
vendored
|
@ -3,8 +3,8 @@ name: LinUtil Preview
|
|||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
run_id:
|
||||
description: 'Run ID of LinUtil Release'
|
||||
tag_name:
|
||||
description: 'Tag name'
|
||||
required: true
|
||||
workflow_run:
|
||||
workflows: ["LinUtil Release"]
|
||||
|
@ -14,29 +14,47 @@ on:
|
|||
jobs:
|
||||
generate_preview:
|
||||
runs-on: ubuntu-latest
|
||||
environment: linutil_env
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout source
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Run ID
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "workflow_run" ]; then
|
||||
echo "run_id=${{ github.event.workflow_run.id }}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "run_id=${{ github.event.inputs.run_id }}" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
- name: Get tag name ( Workflow Run )
|
||||
id: latest_tag
|
||||
uses: actions/github-script@v7
|
||||
if: github.event_name == 'workflow_run'
|
||||
with:
|
||||
name: linutil-artifact
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
run-id: ${{ env.run_id }}
|
||||
script: |
|
||||
const releases = await github.rest.repos.listReleases({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
per_page: 1
|
||||
});
|
||||
core.setOutput('result', releases.data[0].tag_name);
|
||||
result-encoding: string
|
||||
|
||||
- name: Set tag name ( Workflow Run )
|
||||
if: github.event_name == 'workflow_run'
|
||||
run: echo "tag_name=${{ steps.latest_tag.outputs.result }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set tag name ( Workflow Dispatch )
|
||||
if: ${{ github.event_name }} == 'workflow_dispatch'
|
||||
run: echo "tag_name=${{ github.event.inputs.tag_name }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Download binary
|
||||
run: |
|
||||
curl -LO "https://github.com/${{ github.repository }}/releases/download/${{ env.tag_name }}/linutil"
|
||||
|
||||
- name: Set env
|
||||
run: |
|
||||
chmod +x linutil
|
||||
echo "${{ github.workspace }}" >> $GITHUB_PATH
|
||||
mkdir -p build
|
||||
mv linutil build/linutil
|
||||
echo "${{ github.workspace }}/build" >> $GITHUB_PATH
|
||||
|
||||
- name: Generate preview
|
||||
uses: charmbracelet/vhs-action@v2.1.0
|
||||
|
@ -46,10 +64,15 @@ jobs:
|
|||
- name: Move preview
|
||||
run: mv preview.gif docs/assets/preview.gif
|
||||
|
||||
- name: Upload preview
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
- name: Create PR
|
||||
uses: peter-evans/create-pull-request@v7.0.5
|
||||
with:
|
||||
commit_message: Preview for ${{ env.run_id }}
|
||||
file_pattern: "docs/assets/preview.gif"
|
||||
add_options: "--force"
|
||||
commit-message: Preview for ${{ env.tag_name }}
|
||||
file-pattern: "docs/assets/preview.gif"
|
||||
add-options: "--force"
|
||||
token: ${{ secrets.PAT_TOKEN }}
|
||||
branch: feature/preview-${{ env.tag_name }}
|
||||
title: "Update preview for ${{ env.tag_name }}"
|
||||
body: |
|
||||
Automated PR to update preview gif for version ${{ env.tag_name }}
|
||||
if: success()
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
. ../../common-script.sh
|
||||
|
||||
manualInstall() {
|
||||
JETBRAINS_TOOLBOX_DIR="/opt/jetbrains-toolbox"
|
||||
|
||||
case "$ARCH" in
|
||||
x86_64) ARCHIVE_URL=$(curl -s "https://data.services.jetbrains.com/products/releases?code=TBA&latest=true&type=release" | jq -r ".TBA[0].downloads.linux.link") ;;
|
||||
aarch64) ARCHIVE_URL=$(curl -s "https://data.services.jetbrains.com/products/releases?code=TBA&latest=true&type=release" | jq -r ".TBA[0].downloads.linuxARM64.link") ;;
|
||||
esac
|
||||
|
||||
curl -fSL "$ARCHIVE_URL" -o "jetbrains-toolbox.tar.gz"
|
||||
|
||||
if [ -d "$JETBRAINS_TOOLBOX_DIR" ]; then
|
||||
"$ESCALATION_TOOL" rm -rf "$JETBRAINS_TOOLBOX_DIR"
|
||||
fi
|
||||
|
||||
"$ESCALATION_TOOL" mkdir -p "$JETBRAINS_TOOLBOX_DIR"
|
||||
"$ESCALATION_TOOL" tar -xzf "jetbrains-toolbox.tar.gz" -C "$JETBRAINS_TOOLBOX_DIR" --strip-components=1
|
||||
"$ESCALATION_TOOL" ln -sf "$JETBRAINS_TOOLBOX_DIR/jetbrains-toolbox" "/usr/bin/jetbrains-toolbox"
|
||||
}
|
||||
|
||||
installJetBrainsToolBox() {
|
||||
if ! command_exists jetbrains-toolbox; then
|
||||
printf "%b\n" "${YELLOW}Installing Jetbrains Toolbox...${RC}"
|
||||
case "$PACKAGER" in
|
||||
pacman)
|
||||
"$AUR_HELPER" -S --needed --noconfirm jetbrains-toolbox
|
||||
;;
|
||||
dnf)
|
||||
manualInstall
|
||||
;;
|
||||
*)
|
||||
"$ESCALATION_TOOL" "$PACKAGER" install -y libfuse2
|
||||
manualInstall
|
||||
;;
|
||||
esac
|
||||
printf "%b\n" "${GREEN}Successfully installed Jetbrains Toolbox.${RC}"
|
||||
else
|
||||
printf "%b\n" "${GREEN}Jetbrains toolbox is already installed.${RC}"
|
||||
fi
|
||||
}
|
||||
|
||||
checkEnv
|
||||
checkEscalationTool
|
||||
checkAURHelper
|
||||
installJetBrainsToolBox
|
|
@ -54,6 +54,12 @@ description = "GitHub Desktop is a user-friendly application that simplifies the
|
|||
script = "Developer-tools/githubdesktop-setup.sh"
|
||||
task_list = "I"
|
||||
|
||||
[[data.entries]]
|
||||
name = "JetBrains Toolbox"
|
||||
description = "JetBrains Toolbox is a collection of tools and an app that help developers work with JetBrains products."
|
||||
script = "Developer-tools/jetbrains-toolbox.sh"
|
||||
task_list = "I"
|
||||
|
||||
[[data.entries]]
|
||||
name = "Meld"
|
||||
description = "Meld is a visual diff and merge tool that helps compare files, directories, and version-controlled projects."
|
||||
|
|
|
@ -51,6 +51,16 @@ elevated_execution() {
|
|||
fi
|
||||
}
|
||||
|
||||
checkArch() {
|
||||
case "$(uname -m)" in
|
||||
x86_64 | amd64) ARCH="x86_64" ;;
|
||||
aarch64 | arm64) ARCH="aarch64" ;;
|
||||
*) printf "%b\n" "${RED}Unsupported architecture: $(uname -m)${RC}" && exit 1 ;;
|
||||
esac
|
||||
|
||||
printf "%b\n" "${CYAN}System architecture: ${ARCH}${RC}"
|
||||
}
|
||||
|
||||
checkAURHelper() {
|
||||
## Check & Install AUR helper
|
||||
if [ "$PACKAGER" = "pacman" ]; then
|
||||
|
@ -169,6 +179,7 @@ checkDistro() {
|
|||
}
|
||||
|
||||
checkEnv() {
|
||||
checkArch
|
||||
checkEscalationTool
|
||||
checkCommandRequirements "curl groups $ESCALATION_TOOL"
|
||||
checkPackageManager 'nala apt-get dnf pacman zypper'
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
### Developer Tools
|
||||
|
||||
- **Github Desktop**: GitHub Desktop is a user-friendly application that simplifies the process of managing Git repositories and interacting with GitHub, providing a graphical interface for tasks like committing, branching, and syncing changes.
|
||||
- **JetBrains Toolbox**: JetBrains Toolbox is a collection of tools and an app that help developers work with JetBrains products.
|
||||
- **Meld**: Meld is a visual diff and merge tool that helps compare files, directories, and version-controlled projects.
|
||||
- **Neovim**: Neovim is a refactor, and sometimes redactor, in the tradition of Vim.
|
||||
It is not a rewrite but a continuation and extension of Vim.
|
||||
|
|
|
@ -4,7 +4,7 @@ use ego_tree::NodeId;
|
|||
use linutil_core::Tab;
|
||||
use ratatui::{
|
||||
layout::{Position, Rect},
|
||||
style::Style,
|
||||
style::{Color, Style},
|
||||
text::Span,
|
||||
widgets::{Block, Borders, Paragraph},
|
||||
Frame,
|
||||
|
@ -22,6 +22,7 @@ pub struct Filter {
|
|||
in_search_mode: bool,
|
||||
input_position: usize,
|
||||
items: Vec<ListEntry>,
|
||||
completion_preview: Option<String>,
|
||||
}
|
||||
|
||||
impl Filter {
|
||||
|
@ -31,17 +32,23 @@ impl Filter {
|
|||
in_search_mode: false,
|
||||
input_position: 0,
|
||||
items: vec![],
|
||||
completion_preview: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn item_list(&self) -> &[ListEntry] {
|
||||
&self.items
|
||||
}
|
||||
|
||||
pub fn activate_search(&mut self) {
|
||||
self.in_search_mode = true;
|
||||
}
|
||||
|
||||
pub fn deactivate_search(&mut self) {
|
||||
self.in_search_mode = false;
|
||||
self.completion_preview = None;
|
||||
}
|
||||
|
||||
pub fn update_items(&mut self, tabs: &[Tab], current_tab: usize, node: NodeId) {
|
||||
if self.search_input.is_empty() {
|
||||
let curr = tabs[current_tab].tree.get(node).unwrap();
|
||||
|
@ -78,13 +85,34 @@ impl Filter {
|
|||
}
|
||||
self.items.sort_by(|a, b| a.node.name.cmp(&b.node.name));
|
||||
}
|
||||
|
||||
self.update_completion_preview();
|
||||
}
|
||||
|
||||
fn update_completion_preview(&mut self) {
|
||||
if self.search_input.is_empty() {
|
||||
self.completion_preview = None;
|
||||
return;
|
||||
}
|
||||
|
||||
let input = self.search_input.iter().collect::<String>().to_lowercase();
|
||||
self.completion_preview = self.items.iter().find_map(|item| {
|
||||
let item_name_lower = item.node.name.to_lowercase();
|
||||
if item_name_lower.starts_with(&input) {
|
||||
Some(item_name_lower[input.len()..].to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn draw_searchbar(&self, frame: &mut Frame, area: Rect, theme: &Theme) {
|
||||
//Set the search bar text (If empty use the placeholder)
|
||||
let display_text = if !self.in_search_mode && self.search_input.is_empty() {
|
||||
Span::raw("Press / to search")
|
||||
} else {
|
||||
Span::raw(self.search_input.iter().collect::<String>())
|
||||
let input_text = self.search_input.iter().collect::<String>();
|
||||
Span::styled(input_text, Style::default().fg(theme.focused_color()))
|
||||
};
|
||||
|
||||
let search_color = if self.in_search_mode {
|
||||
|
@ -110,11 +138,22 @@ impl Filter {
|
|||
let x = area.x + cursor_position as u16 + 1;
|
||||
let y = area.y + 1;
|
||||
frame.set_cursor_position(Position::new(x, y));
|
||||
|
||||
if let Some(preview) = &self.completion_preview {
|
||||
let preview_span = Span::styled(preview, Style::default().fg(Color::DarkGray));
|
||||
let preview_paragraph = Paragraph::new(preview_span).style(Style::default());
|
||||
let preview_area = Rect::new(
|
||||
x,
|
||||
y,
|
||||
(preview.len() as u16).min(area.width - cursor_position as u16 - 1),
|
||||
1,
|
||||
);
|
||||
frame.render_widget(preview_paragraph, preview_area);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handles key events. Returns true if search must be exited
|
||||
pub fn handle_key(&mut self, event: &KeyEvent) -> SearchAction {
|
||||
//Insert user input into the search bar
|
||||
match event.code {
|
||||
KeyCode::Char('c') if event.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
return self.exit_search()
|
||||
|
@ -124,10 +163,17 @@ impl Filter {
|
|||
KeyCode::Delete => self.remove_next(),
|
||||
KeyCode::Left => return self.cursor_left(),
|
||||
KeyCode::Right => return self.cursor_right(),
|
||||
KeyCode::Tab => return self.complete_search(),
|
||||
KeyCode::Esc => {
|
||||
self.input_position = 0;
|
||||
self.search_input.clear();
|
||||
self.completion_preview = None;
|
||||
return SearchAction::Exit;
|
||||
}
|
||||
KeyCode::Enter => return SearchAction::Exit,
|
||||
KeyCode::Esc => return self.exit_search(),
|
||||
_ => return SearchAction::None,
|
||||
};
|
||||
self.update_completion_preview();
|
||||
SearchAction::Update
|
||||
}
|
||||
|
||||
|
@ -141,16 +187,19 @@ impl Filter {
|
|||
self.input_position = self.input_position.saturating_sub(1);
|
||||
SearchAction::None
|
||||
}
|
||||
|
||||
fn cursor_right(&mut self) -> SearchAction {
|
||||
if self.input_position < self.search_input.len() {
|
||||
self.input_position += 1;
|
||||
}
|
||||
SearchAction::None
|
||||
}
|
||||
|
||||
fn insert_char(&mut self, input: char) {
|
||||
self.search_input.insert(self.input_position, input);
|
||||
self.cursor_right();
|
||||
}
|
||||
|
||||
fn remove_previous(&mut self) {
|
||||
let current = self.input_position;
|
||||
if current > 0 {
|
||||
|
@ -158,12 +207,25 @@ impl Filter {
|
|||
self.cursor_left();
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_next(&mut self) {
|
||||
let current = self.input_position;
|
||||
if current < self.search_input.len() {
|
||||
self.search_input.remove(current);
|
||||
}
|
||||
}
|
||||
|
||||
fn complete_search(&mut self) -> SearchAction {
|
||||
if let Some(completion) = self.completion_preview.take() {
|
||||
self.search_input.extend(completion.chars());
|
||||
self.input_position = self.search_input.len();
|
||||
self.update_completion_preview();
|
||||
SearchAction::Update
|
||||
} else {
|
||||
SearchAction::None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_search(&mut self) {
|
||||
self.search_input.clear();
|
||||
self.input_position = 0;
|
||||
|
|
Loading…
Reference in New Issue
Block a user