Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 48 additions & 20 deletions .github/changelog.tera
Original file line number Diff line number Diff line change
Expand Up @@ -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 -%}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,5 @@ $RECYCLE.BIN/
*.lnk

.env

docs/superpowers
50 changes: 33 additions & 17 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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)

- - -

Expand All @@ -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)
20 changes: 10 additions & 10 deletions cog.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
13 changes: 11 additions & 2 deletions functions/_fifc_completion_group.fish
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 27 additions & 0 deletions functions/_fifc_is_generic_path.fish
Original file line number Diff line number Diff line change
@@ -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
24 changes: 23 additions & 1 deletion tests/test_group.fish
Original file line number Diff line number Diff line change
@@ -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
55 changes: 55 additions & 0 deletions tests/test_is_generic.fish
Original file line number Diff line number Diff line change
@@ -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
Loading