From 790dcf6cb43f54192e569e0c21a42bd462c159f0 Mon Sep 17 00:00:00 2001 From: gazorby Date: Mon, 20 Jul 2026 00:09:45 +0200 Subject: [PATCH 1/2] refactor: improve detection of current dir completion --- .gitignore | 2 + functions/_fifc_completion_group.fish | 13 ++++++- functions/_fifc_is_generic_path.fish | 27 +++++++++++++ tests/test_group.fish | 24 +++++++++++- tests/test_is_generic.fish | 55 +++++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 functions/_fifc_is_generic_path.fish create mode 100644 tests/test_is_generic.fish diff --git a/.gitignore b/.gitignore index d0f8088..085161e 100644 --- a/.gitignore +++ b/.gitignore @@ -84,3 +84,5 @@ $RECYCLE.BIN/ *.lnk .env + +docs/superpowers diff --git a/functions/_fifc_completion_group.fish b/functions/_fifc_completion_group.fish index d861b8d..714e492 100644 --- a/functions/_fifc_completion_group.fish +++ b/functions/_fifc_completion_group.fish @@ -6,11 +6,20 @@ function _fifc_completion_group -d "Determine completion group" # Directories set -l dir_test "test -d $complist[1]" set dir_test (string join -- " -a -d " $dir_test $complist[2..-1]) - if test -n "$is_null"; and eval "$dir_test" + + # Only treat the completion as file/dir path completion when fish's list is + # the plain listing of the completed dir. Otherwise fish is offering specific + # paths (e.g. `git worktree remove`), which must be forwarded unchanged. + set -l generic 0 + if test -n "$is_null"; and _fifc_is_generic_path "$path_candidate" + set generic 1 + end + + if test "$generic" = 1; and eval "$dir_test" echo directories # Files # When complist is big, avoid calling ls with all arguments if first is neither a file nor a directory - else if test -n "$is_null"; and echo $complist | xargs ls -d -- &>/dev/null + else if test "$generic" = 1; and echo $complist | xargs ls -d -- &>/dev/null echo files # Options else if string match --regex --quiet -- '\h+\-+\h*$' $fifc_commandline diff --git a/functions/_fifc_is_generic_path.fish b/functions/_fifc_is_generic_path.fish new file mode 100644 index 0000000..03949dc --- /dev/null +++ b/functions/_fifc_is_generic_path.fish @@ -0,0 +1,27 @@ +function _fifc_is_generic_path -d "True when fish's completions equal the plain listing (all entries, or directories only) of the completed dir" + set -l dir $argv[1] + set -l listing + # Include dotfiles only when the target path itself refers to hidden entries + if string match --quiet -- "*." "$dir" + set listing (command ls -1A -- $dir 2>/dev/null) + else + set listing (command ls -1 -- $dir 2>/dev/null) + end + # Directory-only subset, for directory completers (cd, pushd, rmdir, ...) + set -l base (string replace --regex -- '/$' '' "$dir") + set -l dirs + for entry in $listing + if test -d "$base/$entry" + set -a dirs $entry + end + end + # Reduce each fish completion to a bare name: strip trailing slash, then dir prefix + set -l names + for entry in (_fifc_expand_tilde (_fifc_parse_complist)) + set -a names (string replace --regex -- '^.*/' '' (string replace --regex -- '/$' '' $entry)) + end + set -l sorted_names (printf '%s\n' $names | sort -u) + set -l sorted_listing (printf '%s\n' $listing | sort -u) + set -l sorted_dirs (printf '%s\n' $dirs | sort -u) + test "$sorted_names" = "$sorted_listing"; or test "$sorted_names" = "$sorted_dirs" +end diff --git a/tests/test_group.fish b/tests/test_group.fish index 2c2e5d0..a9da29b 100644 --- a/tests/test_group.fish +++ b/tests/test_group.fish @@ -1,23 +1,45 @@ +set curr_fifc_token $fifc_token set _fifc_complist_path (mktemp) set _commandline "kill " complete -C --escape -- "$_commandline" >$_fifc_complist_path set fifc_commandline "$_commandline" +set fifc_token "" set actual (_fifc_completion_group) @test "group test pid" "$actual" = processes set _commandline "ls tests/_resources/dir\ with\ spaces/" complete -C --escape -- "$_commandline" >$_fifc_complist_path set fifc_commandline "$_commandline" +set fifc_token "tests/_resources/dir with spaces/" set actual (_fifc_completion_group) @test "group test files" "$actual" = files set _commandline "ls -" complete -C --escape -- "$_commandline" >$_fifc_complist_path set fifc_commandline "$_commandline" +set fifc_token - set actual (_fifc_completion_group) @test "group test options" "$actual" = options -set -e _fifc_complist +# Specific path completion (fish offers the worktree path, not the cwd listing): +# must NOT be treated as generic directory completion. +set _commandline "git worktree remove " +complete -C --escape -- "$_commandline" >$_fifc_complist_path +set fifc_commandline "$_commandline" +set fifc_token "" +set actual (_fifc_completion_group) +@test "group test specific path is not directories" "$actual" != directories + +# Directory-only completer (cd) must remain classified as directories (recursive fd). +set _commandline "cd " +complete -C --escape -- "$_commandline" >$_fifc_complist_path +set fifc_commandline "$_commandline" +set fifc_token "" +set actual (_fifc_completion_group) +@test "group test directory completer stays directories" "$actual" = directories + set -e fifc_commandline +set fifc_token $curr_fifc_token command $fifc_rm_cmd $_fifc_complist_path +set -e _fifc_complist_path diff --git a/tests/test_is_generic.fish b/tests/test_is_generic.fish new file mode 100644 index 0000000..11c07f0 --- /dev/null +++ b/tests/test_is_generic.fish @@ -0,0 +1,55 @@ +set curr_fifc_token $fifc_token +set curr_home $HOME +set _fifc_complist_path (mktemp) + +# Case a: bare completion of the cwd is generic +complete -C --escape -- "cat " >$_fifc_complist_path +if _fifc_is_generic_path "$PWD/" + set actual true +else + set actual false +end +@test "is_generic: bare cwd completion is generic" "$actual" = true + +# Case b: a single specific directory path (not a cwd entry) is not generic +set specific_dir (mktemp -d) +echo "$specific_dir" >$_fifc_complist_path +if _fifc_is_generic_path "$PWD/" + set actual true +else + set actual false +end +@test "is_generic: specific path is not generic" "$actual" = false +command rm -rf "$specific_dir" + +# Case c: tilde-form listing of a sub-directory is generic +set test_home (mktemp -d) +set -gx HOME "$test_home" +mkdir -p "$HOME/sub" +touch "$HOME/sub/a.txt" "$HOME/sub/b.txt" +printf '%s\n' '~/sub/a.txt' '~/sub/b.txt' >$_fifc_complist_path +if _fifc_is_generic_path "$HOME/sub/" + set actual true +else + set actual false +end +@test "is_generic: tilde subdir listing is generic" "$actual" = true + +# Case d: a directory-only completer (cd) is generic against a dir with files + subdirs +set gen_dir (mktemp -d) +mkdir -p "$gen_dir/sub1" "$gen_dir/sub2" +touch "$gen_dir/file.txt" +printf '%s\n' sub1/ sub2/ >$_fifc_complist_path +if _fifc_is_generic_path "$gen_dir/" + set actual true +else + set actual false +end +@test "is_generic: directory-only listing is generic" "$actual" = true +command rm -rf "$gen_dir" + +command rm -rf "$test_home" +set -gx HOME "$curr_home" +command rm -f $_fifc_complist_path +set -e _fifc_complist_path +set fifc_token $curr_fifc_token From ef236e80eee56b08c0f530bb62d95aa65fc57a39 Mon Sep 17 00:00:00 2001 From: gazorby Date: Mon, 20 Jul 2026 00:10:51 +0200 Subject: [PATCH 2/2] build: update changelog template --- .github/changelog.tera | 68 +++++++++++++++++++++++++++++------------- CHANGELOG.md | 50 ++++++++++++++++++++----------- cog.toml | 20 ++++++------- 3 files changed, 91 insertions(+), 47 deletions(-) diff --git a/.github/changelog.tera b/.github/changelog.tera index a0d62cd..ada5e0d 100644 --- a/.github/changelog.tera +++ b/.github/changelog.tera @@ -13,39 +13,67 @@ ## Unreleased ([{{ from_shorthand ~ ".." ~ to_shorthand }}]({{repository_url ~ "/compare/" ~ from_shorthand ~ ".." ~ to_shorthand}})) {% endif -%} -{% for value in commits | group_by_type-%} +{% for value in commits | group_by_type -%} #### {{ value.0 | upper_first }} +{% set_global type_commits = [] -%} +{% set_global seen = [] -%} +{#- Collect this type's commits: scoped (grouped and sorted by scope) first, then unscoped -#} {% for scope, scoped_commits in value.1 | group_by(attribute="scope") -%} -{% for commit in scoped_commits | sort(attribute="scope") -%} -{%- set line = macros::remote(commit=commit) -%} -{%- if repository_url and commit.summary is matching("\(#\d+\)$") -%} - {%- set num = commit.summary | split(pat="(#") | last | trim_end_matches(pat=")") -%} - {%- set line = line | replace(from="(#" ~ num ~ ")", to="([#" ~ num ~ "](" ~ repository_url ~ "/pull/" ~ num ~ "))") -%} -{%- endif -%} -{{ line }} -{% endfor -%} + {% for commit in scoped_commits | sort(attribute="scope") -%} + {%- set_global type_commits = type_commits | concat(with=commit) -%} + {% endfor -%} {% endfor -%} - {% for commit in value.1 | unscoped -%} -{%- set line = macros::remote(commit=commit) -%} -{%- if repository_url and commit.summary is matching("\(#\d+\)$") -%} - {%- set num = commit.summary | split(pat="(#") | last | trim_end_matches(pat=")") -%} - {%- set line = line | replace(from="(#" ~ num ~ ")", to="([#" ~ num ~ "](" ~ repository_url ~ "/pull/" ~ num ~ "))") -%} -{%- endif -%} + {%- set_global type_commits = type_commits | concat(with=commit) -%} +{% endfor -%} +{% for commit in type_commits -%} + {#- Omit a repeated commit: skip when this scope + summary was already rendered in this section -#} + {%- set key = commit.summary -%} + {%- if commit.scope -%} + {%- set key = commit.scope ~ "|" ~ commit.summary -%} + {%- endif -%} + {%- if key not in seen -%} + {%- set_global seen = seen | concat(with=key) -%} + {%- set line = macros::remote(commit=commit) -%} + {#- Link an unmapped author's plain signature (no space) to their profile, mirroring the macro's mapped-author link -#} + {%- if not commit.author and repository_url and not (commit.signature is matching(" ")) -%} + {%- set line = line | replace(from=")) - " ~ commit.signature, to=")) - [@" ~ commit.signature ~ "](" ~ platform ~ "/" ~ commit.signature ~ ")") -%} + {%- endif -%} + {#- Turn a trailing PR reference "(#123)" into a link to the pull request -#} + {%- if repository_url and commit.summary is matching("\(#\d+\)$") -%} + {%- set num = commit.summary | split(pat="(#") | last | trim_end_matches(pat=")") -%} + {%- set line = line | replace(from="(#" ~ num ~ ")", to="([#" ~ num ~ "](" ~ repository_url ~ "/pull/" ~ num ~ "))") -%} + {%- endif -%} {{ line }} +{% endif -%} {% endfor -%} {% endfor -%} +{#- Collect unique contributors: mapped authors, unmapped spaceless signatures, and co-authors, linked when possible -#} {% set_global contributors = [] -%} {% for commit in commits -%} -{%- if commit.author -%}{% set_global contributors = contributors | concat(with=commit.author) %}{%- endif -%} -{%- for footer in commit.footers -%} -{%- if footer.github_co_authored_by and footer.github_co_authored_by.username -%}{% set_global contributors = contributors | concat(with=footer.github_co_authored_by.username) %}{%- endif -%} -{%- endfor -%} + {%- if commit.author -%} + {%- set_global contributors = contributors | concat(with="[@" ~ commit.author ~ "](" ~ platform ~ "/" ~ commit.author ~ ")") -%} + {%- elif commit.signature is matching(" ") -%} + {%- set_global contributors = contributors | concat(with=commit.signature) -%} + {%- else -%} + {%- set_global contributors = contributors | concat(with="[@" ~ commit.signature ~ "](" ~ platform ~ "/" ~ commit.signature ~ ")") -%} + {%- endif -%} + {%- for footer in commit.footers -%} + {%- if footer.github_co_authored_by and footer.github_co_authored_by.username -%} + {%- set_global contributors = contributors | concat(with="[@" ~ footer.github_co_authored_by.username ~ "](" ~ platform ~ "/" ~ footer.github_co_authored_by.username ~ ")") -%} + {%- elif footer.github_co_authored_by and footer.github_co_authored_by.user -%} + {%- if footer.github_co_authored_by.user is matching(" ") -%} + {%- set_global contributors = contributors | concat(with=footer.github_co_authored_by.user) -%} + {%- else -%} + {%- set_global contributors = contributors | concat(with="[@" ~ footer.github_co_authored_by.user ~ "](" ~ platform ~ "/" ~ footer.github_co_authored_by.user ~ ")") -%} + {%- endif -%} + {%- endif -%} + {%- endfor -%} {%- endfor -%} {%- set contributors = contributors | unique | sort -%} {% if contributors | length > 0 %} #### 🤝️ Contributors -{% for c in contributors %}- [@{{ c }}]({{ platform }}/{{ c }}) +{% for c in contributors %}- {{ c }} {% endfor -%} {% endif -%} diff --git a/CHANGELOG.md b/CHANGELOG.md index 9082310..8ef1260 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,15 @@ -## [v0.2.3](https://github.com/gazorby/fifc/compare/v0.2.2..v0.2.3) - 2026-07-16 -#### 🐛 Bug Fixes -- restore fzf options set by rules - ([b37cacd](https://github.com/gazorby/fifc/commit/b37cacdf407d849bc3d14a7defdef400beba7c4a)) - [@gazorby](https://github.com/gazorby) -#### ⚙️ Miscellaneous Tasks -- (**cog**) add manual ump profile; validate commit msg in pre-commit - ([b47a21f](https://github.com/gazorby/fifc/commit/b47a21fb1bfdd372f1a00c7b407a0a85a55052e5)) - [@gazorby](https://github.com/gazorby) -- fix fishtape job input - ([1778394](https://github.com/gazorby/fifc/commit/1778394bb7c4891a779aaffddfd527d565b136cd)) - [@gazorby](https://github.com/gazorby) -- fix test not installing plugin from the current branch - ([53cbc6f](https://github.com/gazorby/fifc/commit/53cbc6fd51b51d4c26b016d8267906c797d2cfdd)) - [@gazorby](https://github.com/gazorby) -- use latest cocogitto version - ([643d908](https://github.com/gazorby/fifc/commit/643d9081c63de6947e03bdecbb9703e6aa65c6ff)) - [@gazorby](https://github.com/gazorby) +## Unreleased ([0e7d013..790dcf6](https://github.com/gazorby/fifc/compare/0e7d013..790dcf6)) +#### 🚜 Refactor +- improve detection of current dir completion - ([790dcf6](https://github.com/gazorby/fifc/commit/790dcf6cb43f54192e569e0c21a42bd462c159f0)) - [@gazorby](https://github.com/gazorby) #### 🤝️ Contributors - [@gazorby](https://github.com/gazorby) - - - -## [v0.2.4](https://github.com/gazorby/fifc/compare/0c813458b20d318c927a3f52b584e1afa4b578a8..v0.2.4) - 2026-07-17 + +## [v0.2.4](https://github.com/gazorby/fifc/compare/v0.2.3..v0.2.4) - 2026-07-18 #### 🐛 Bug Fixes -- Fixes for paths that start with `~` ([#76](https://github.com/gazorby/fifc/pull/76)) - ([d1d87cd](https://github.com/gazorby/fifc/commit/d1d87cdf8d34b6e731ead94d100ca7186cce576b)) - justbispo +- Fixes for paths that start with `~` ([#76](https://github.com/gazorby/fifc/pull/76)) - ([d1d87cd](https://github.com/gazorby/fifc/commit/d1d87cdf8d34b6e731ead94d100ca7186cce576b)) - [@justbispo](https://github.com/justbispo) #### ⚙️ Miscellaneous Tasks - (**labelers**) update config - ([a126de7](https://github.com/gazorby/fifc/commit/a126de710d0336a013a99f64c8d9faaf7933d3e7)) - [@gazorby](https://github.com/gazorby) - update pr title lint workflow - ([386f705](https://github.com/gazorby/fifc/commit/386f705dcf009d76561609be987ffdf3399eabaa)) - [@gazorby](https://github.com/gazorby) @@ -23,9 +19,23 @@ #### 🤝️ Contributors - [@gazorby](https://github.com/gazorby) +- [@justbispo](https://github.com/justbispo) - - - +## [v0.2.3](https://github.com/gazorby/fifc/compare/v0.2.2..v0.2.3) - 2026-07-16 +#### 🐛 Bug Fixes +- restore fzf options set by rules - ([b37cacd](https://github.com/gazorby/fifc/commit/b37cacdf407d849bc3d14a7defdef400beba7c4a)) - [@gazorby](https://github.com/gazorby) +#### ⚙️ Miscellaneous Tasks +- (**cog**) add manual ump profile; validate commit msg in pre-commit - ([b47a21f](https://github.com/gazorby/fifc/commit/b47a21fb1bfdd372f1a00c7b407a0a85a55052e5)) - [@gazorby](https://github.com/gazorby) +- fix fishtape job input - ([1778394](https://github.com/gazorby/fifc/commit/1778394bb7c4891a779aaffddfd527d565b136cd)) - [@gazorby](https://github.com/gazorby) +- fix test not installing plugin from the current branch - ([53cbc6f](https://github.com/gazorby/fifc/commit/53cbc6fd51b51d4c26b016d8267906c797d2cfdd)) - [@gazorby](https://github.com/gazorby) +- use latest cocogitto version - ([643d908](https://github.com/gazorby/fifc/commit/643d9081c63de6947e03bdecbb9703e6aa65c6ff)) - [@gazorby](https://github.com/gazorby) + +#### 🤝️ Contributors +- [@gazorby](https://github.com/gazorby) + +- - - ## [v0.2.2](https://github.com/gazorby/fifc/compare/v0.2.1..v0.2.2) - 2026-07-14 #### ⚙️ Miscellaneous Tasks @@ -47,18 +57,18 @@ - - - ## [v0.2.0](https://github.com/gazorby/fifc/compare/v0.1.1..v0.2.0) - 2026-07-14 -#### 🚜 Refactor -- replace exa with eza ([#70](https://github.com/gazorby/fifc/pull/70)) - ([220dbdc](https://github.com/gazorby/fifc/commit/220dbdc15352f67d6ad0bdf2175a280e186ca047)) - [@gazorby](https://github.com/gazorby) #### 🚀 Features - better fzf result navigation ([#72](https://github.com/gazorby/fifc/pull/72)) - ([397e171](https://github.com/gazorby/fifc/commit/397e171edbdc460e49f1c3cb5ac5cefe0e165e3b)) - [@gazorby](https://github.com/gazorby) #### 🐛 Bug Fixes -- (**fifc**) fix command not found in preview - ([8ef00c6](https://github.com/gazorby/fifc/commit/8ef00c6d849dd54642113e5747e1f689e29370ed)) - command_block +- (**fifc**) fix command not found in preview - ([8ef00c6](https://github.com/gazorby/fifc/commit/8ef00c6d849dd54642113e5747e1f689e29370ed)) - [@command_block](https://github.com/command_block) - remove extra tab binding ([#61](https://github.com/gazorby/fifc/pull/61)) - ([5f3f5a8](https://github.com/gazorby/fifc/commit/5f3f5a8a96670fac032a923de7ec1602a132b31c)) - Maciej Piasecki - rule initialization - ([a01650c](https://github.com/gazorby/fifc/commit/a01650cd432becdc6e36feeff5e8d657bd7ee84a)) - [@gazorby](https://github.com/gazorby) -- variables will die in fzf's fish, no erase needed - ([6681b51](https://github.com/gazorby/fifc/commit/6681b51d1a5e82eb87a919448a495dba49932bb6)) - phanium -- don't escape environment variable in completion - ([457cec0](https://github.com/gazorby/fifc/commit/457cec0bbdcc93d884729e7ccd2dc82a94caee59)) - phanium +- variables will die in fzf's fish, no erase needed - ([6681b51](https://github.com/gazorby/fifc/commit/6681b51d1a5e82eb87a919448a495dba49932bb6)) - [@phanium](https://github.com/phanium) +- don't escape environment variable in completion - ([457cec0](https://github.com/gazorby/fifc/commit/457cec0bbdcc93d884729e7ccd2dc82a94caee59)) - [@phanium](https://github.com/phanium) #### ⚡ Performance -- (**startup**) skip load of fifc rules when in interactive shell - ([64433fa](https://github.com/gazorby/fifc/commit/64433fa58b7d102f18eb2160d52ef706296cb585)) - phanium +- (**startup**) skip load of fifc rules when in interactive shell - ([64433fa](https://github.com/gazorby/fifc/commit/64433fa58b7d102f18eb2160d52ef706296cb585)) - [@phanium](https://github.com/phanium) +#### 🚜 Refactor +- replace exa with eza ([#70](https://github.com/gazorby/fifc/pull/70)) - ([220dbdc](https://github.com/gazorby/fifc/commit/220dbdc15352f67d6ad0bdf2175a280e186ca047)) - [@gazorby](https://github.com/gazorby) #### 📚 Documentation - (**readme**) update - ([2ee5bee](https://github.com/gazorby/fifc/commit/2ee5beec7dfd28101026357633616a211fe240ae)) - [@gazorby](https://github.com/gazorby) - update readme - ([58aaa95](https://github.com/gazorby/fifc/commit/58aaa95d038f157180f831fce2afdec5179f843e)) - [@gazorby](https://github.com/gazorby) @@ -77,7 +87,10 @@ - run prettier - ([8bd370c](https://github.com/gazorby/fifc/commit/8bd370c4a5db3b71f52a3079b758f0f2ed082044)) - [@gazorby](https://github.com/gazorby) #### 🤝️ Contributors +- Maciej Piasecki +- [@command_block](https://github.com/command_block) - [@gazorby](https://github.com/gazorby) +- [@phanium](https://github.com/phanium) - - - @@ -94,4 +107,7 @@ ## [v0.1.0](https://github.com/gazorby/fifc/compare/96dd5ab27cd91d6fe7f15753ee92253f2d4ba164..v0.1.0) - 2023-01-23 #### 🚀 Features -- use `$EDITOR` as default editor - ([8da1d3a](https://github.com/gazorby/fifc/commit/8da1d3af9f7929b0f743ebf8403a0a458b514cc3)) - Kid +- use `$EDITOR` as default editor - ([8da1d3a](https://github.com/gazorby/fifc/commit/8da1d3af9f7929b0f743ebf8403a0a458b514cc3)) - [@Kid](https://github.com/Kid) + +#### 🤝️ Contributors +- [@Kid](https://github.com/Kid) diff --git a/cog.toml b/cog.toml index 959cffe..fb3c80a 100644 --- a/cog.toml +++ b/cog.toml @@ -22,16 +22,16 @@ authors = [ ] [commit_types] -feat = { changelog_title = "🚀 Features" } -fix = { changelog_title = "🐛 Bug Fixes" } -docs = { changelog_title = "📚 Documentation" } -perf = { changelog_title = "⚡ Performance" } -refactor = { changelog_title = "🚜 Refactor" } -ref = { changelog_title = "🚜 Refactor" } -style = { changelog_title = "🎨 Styling" } -build = { changelog_title = "⚙️ Miscellaneous Tasks" } -ci = { changelog_title = "⚙️ Miscellaneous Tasks" } -revert = { changelog_title = "◀️ Revert" } +feat = { changelog_title = "🚀 Features", order = 1 } +fix = { changelog_title = "🐛 Bug Fixes", order = 2 } +perf = { changelog_title = "⚡ Performance", order = 3 } +refactor = { changelog_title = "🚜 Refactor", order = 4 } +ref = { changelog_title = "🚜 Refactor", order = 4 } +revert = { changelog_title = "◀️ Revert", order = 5 } +docs = { changelog_title = "📚 Documentation", order = 6 } +build = { changelog_title = "⚙️ Miscellaneous Tasks", order = 7 } +ci = { changelog_title = "⚙️ Miscellaneous Tasks", order = 7 } +style = { changelog_title = "🎨 Styling", order = 8 } chore = { omit_from_changelog = true } test = { omit_from_changelog = true }