From 6eba207f2728ddd76670130ae47e766b3d22b297 Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Fri, 1 Nov 2024 13:36:23 -0500 Subject: [PATCH 1/9] Preview Commit to PR fix --- .github/workflows/preview.yml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 82bd17f1..bb63b2d5 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -46,10 +46,16 @@ jobs: - name: Move preview run: mv preview.gif docs/assets/preview.gif - - name: Upload preview - uses: stefanzweifel/git-auto-commit-action@v5 + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 with: - commit_message: Preview for ${{ env.run_id }} - file_pattern: "docs/assets/preview.gif" - add_options: "--force" + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Preview for ${{ env.run_id }} + title: 'Update preview GIF' + body: 'Automatically generated preview GIF from workflow run ${{ env.run_id }}' + branch: update-preview-gif + base: main + delete-branch: true + add-paths: | + docs/assets/preview.gif if: success() From 904ea6ee536e0a5401ba40c0d177a18e89708531 Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Sat, 2 Nov 2024 00:13:05 +0530 Subject: [PATCH 2/9] refact(ci): Preview workflow to create PR (#901) * refact: use tags instead of runner id * refact: pr instead of auto commit --------- Co-authored-by: Chris Titus --- .github/workflows/linutil.yml | 8 ---- .github/workflows/preview.yml | 72 +++++++++++++++++++++-------------- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/.github/workflows/linutil.yml b/.github/workflows/linutil.yml index 1184549b..187f1e54 100644 --- a/.github/workflows/linutil.yml +++ b/.github/workflows/linutil.yml @@ -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 \ No newline at end of file diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index bb63b2d5..e79fbdfe 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -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,46 @@ on: jobs: generate_preview: runs-on: ubuntu-latest + 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 + }); + return 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,16 +63,15 @@ jobs: - name: Move preview run: mv preview.gif docs/assets/preview.gif - - name: Create Pull Request - uses: peter-evans/create-pull-request@v6 + - name: Create PR + uses: peter-evans/create-pull-request@v7.0.5 with: - token: ${{ secrets.GITHUB_TOKEN }} - commit-message: Preview for ${{ env.run_id }} - title: 'Update preview GIF' - body: 'Automatically generated preview GIF from workflow run ${{ env.run_id }}' - branch: update-preview-gif - base: main + title: "release: Preview for ${{ env.tag_name }}" + commit-message: "release: Preview for ${{ env.tag_name }}" + branch: "preview-${{ env.tag_name }}" delete-branch: true - add-paths: | - docs/assets/preview.gif - if: success() + labels: "documentation" + body: | + ## Preview for ${{ env.tag_name }} + - Tag: [${{ env.tag_name }}](https://github.com/${{ github.repository }}/tree/${{ env.tag_name }}) + - Preview: ![Preview](https://raw.githubusercontent.com/${{ github.repository }}/preview-${{ env.tag_name }}/docs/assets/preview.gif) From 808ef913e537d831ea1211095c2151665ae7748b Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Sat, 2 Nov 2024 00:15:39 +0530 Subject: [PATCH 3/9] refact: use tags instead of runner id (#900) Co-authored-by: Chris Titus --- .github/workflows/preview.yml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index e79fbdfe..6b5d8ee1 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -16,7 +16,6 @@ jobs: runs-on: ubuntu-latest permissions: contents: write - pull-requests: write steps: - name: Checkout source @@ -66,12 +65,7 @@ jobs: - name: Create PR uses: peter-evans/create-pull-request@v7.0.5 with: - title: "release: Preview for ${{ env.tag_name }}" - commit-message: "release: Preview for ${{ env.tag_name }}" - branch: "preview-${{ env.tag_name }}" - delete-branch: true - labels: "documentation" - body: | - ## Preview for ${{ env.tag_name }} - - Tag: [${{ env.tag_name }}](https://github.com/${{ github.repository }}/tree/${{ env.tag_name }}) - - Preview: ![Preview](https://raw.githubusercontent.com/${{ github.repository }}/preview-${{ env.tag_name }}/docs/assets/preview.gif) + commit_message: Preview for ${{ env.tag_name }} + file_pattern: "docs/assets/preview.gif" + add_options: "--force" + if: success() From 1dec242548e413dd2bec40bc9bf639d6206aef9d Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Fri, 1 Nov 2024 14:27:58 -0500 Subject: [PATCH 4/9] add pr write privs --- .github/workflows/preview.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 6b5d8ee1..b3cba357 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -16,6 +16,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: write + pull-requests: write steps: - name: Checkout source From 951cdc2d4c43f1ab09d2d2b1d31f92828bcec4b5 Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Sat, 2 Nov 2024 00:59:01 +0530 Subject: [PATCH 5/9] feat: jetbrains-toolbox (#893) * feat: jetbrains-toolbox * fix: formatting and shebang * Forgot the docs --- .../Developer-tools/jetbrains-toolbox.sh | 48 +++++++++++++++++++ core/tabs/applications-setup/tab_data.toml | 6 +++ core/tabs/common-script.sh | 11 +++++ docs/userguide.md | 1 + 4 files changed, 66 insertions(+) create mode 100644 core/tabs/applications-setup/Developer-tools/jetbrains-toolbox.sh diff --git a/core/tabs/applications-setup/Developer-tools/jetbrains-toolbox.sh b/core/tabs/applications-setup/Developer-tools/jetbrains-toolbox.sh new file mode 100644 index 00000000..79ce360e --- /dev/null +++ b/core/tabs/applications-setup/Developer-tools/jetbrains-toolbox.sh @@ -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 diff --git a/core/tabs/applications-setup/tab_data.toml b/core/tabs/applications-setup/tab_data.toml index c102a5ce..44b74464 100644 --- a/core/tabs/applications-setup/tab_data.toml +++ b/core/tabs/applications-setup/tab_data.toml @@ -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." diff --git a/core/tabs/common-script.sh b/core/tabs/common-script.sh index 7c205edd..a9dd5d62 100644 --- a/core/tabs/common-script.sh +++ b/core/tabs/common-script.sh @@ -43,6 +43,16 @@ checkFlatpak() { 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 @@ -156,6 +166,7 @@ checkDistro() { } checkEnv() { + checkArch checkEscalationTool checkCommandRequirements "curl groups $ESCALATION_TOOL" checkPackageManager 'nala apt-get dnf pacman zypper' diff --git a/docs/userguide.md b/docs/userguide.md index 46a3f99b..8ad704e6 100644 --- a/docs/userguide.md +++ b/docs/userguide.md @@ -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. From 6f217189633f2a8c896990530ec3c2e254066f56 Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Fri, 1 Nov 2024 15:04:07 -0500 Subject: [PATCH 6/9] change to PAT Token --- .github/workflows/preview.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index b3cba357..bf242600 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -14,6 +14,7 @@ on: jobs: generate_preview: runs-on: ubuntu-latest + environment: linutil_env permissions: contents: write pull-requests: write @@ -66,7 +67,12 @@ jobs: - name: Create PR uses: peter-evans/create-pull-request@v7.0.5 with: - commit_message: Preview for ${{ env.tag_name }} - 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() From 00d321d75ea8f3502ebdc3a01c3fffc823993653 Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Fri, 1 Nov 2024 15:15:35 -0500 Subject: [PATCH 7/9] fix tag output --- .github/workflows/preview.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index bf242600..4967eeef 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -26,7 +26,7 @@ jobs: - name: Get tag name ( Workflow Run ) id: latest_tag uses: actions/github-script@v7 - if: ${{ github.event_name }} == 'workflow_run' + if: github.event_name == 'workflow_run' with: script: | const releases = await github.rest.repos.listReleases({ @@ -34,11 +34,11 @@ jobs: repo: context.repo.repo, per_page: 1 }); - return releases.data[0].tag_name; + core.setOutput('result', releases.data[0].tag_name); result-encoding: string - name: Set tag name ( Workflow Run ) - if: ${{ github.event_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 ) From 58f3433de63a1e6c432ef5ef0de4d75ddd2da0c0 Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Fri, 1 Nov 2024 15:18:12 -0500 Subject: [PATCH 8/9] fix doc privs for pushing new prs to docs --- .github/workflows/github-pages.yml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml index 30e992d4..94ca5e3c 100644 --- a/.github/workflows/github-pages.yml +++ b/.github/workflows/github-pages.yml @@ -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 "\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 From 5878f4dbf0b5b82ca48342c4883a6d8e813bf63f Mon Sep 17 00:00:00 2001 From: nyx Date: Fri, 1 Nov 2024 17:01:01 -0400 Subject: [PATCH 9/9] implement fish like tab completion (#767) * implement fish like tab completion * grey the pv out and convert to lowercase * run fmt * do not tabcomplete if the user hits enter * fix * fix lints * run docgen --------- Co-authored-by: nyx Co-authored-by: Adam Perkowski --- tui/src/filter.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/tui/src/filter.rs b/tui/src/filter.rs index cd6063fc..898fee74 100644 --- a/tui/src/filter.rs +++ b/tui/src/filter.rs @@ -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, + completion_preview: Option, } 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::().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::()) + let input_text = self.search_input.iter().collect::(); + 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;