Skip to content

Commit cedd8ca

Browse files
authored
Merge branch 'nushell:main' into aerospace
2 parents 49ef6d1 + a19339c commit cedd8ca

File tree

28 files changed

+5911
-962
lines changed

28 files changed

+5911
-962
lines changed
Lines changed: 6 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,8 @@
1-
# auto-generate completions
1+
# Note
22

3-
- basic helpers to parse --help information from cli commands and export nu completions source
4-
- basic helpers tp parse .fish complete files and export nu completions source
3+
Completions in this directory were generated via the auto-generate scripts.
4+
These scripts are currently outdated and will not work in recent releases
5+
of Nushell. The scripts themselves have been moved to `<repo_root>/need-update/custom-completions/auto-generate`
6+
until they are updated.
57

6-
# parse-fish
7-
8-
## current
9-
- only parses out simple complete's with no complete's boolean arguments like -f
10-
- does not map fish autocomplete helpers to nu-complete helps (a nu library of autocomplete utils would be neat)
11-
12-
## usage
13-
14-
be in a directory with one or more .fish completion scripts
15-
16-
A good one is
17-
18-
`git clone https://github.com/fish-shell/fish-shell`
19-
`cd fish-shell/share/completions`
20-
21-
To build all .fish files in the current directory `build-completions-from-pwd`
22-
23-
```nu
24-
build-completions-from-pwd
25-
ls *.nu
26-
```
27-
28-
To build a single .fish file and choose the output file
29-
```nu
30-
build-completion cargo.fish cargo.nu
31-
```
32-
# parse-help
33-
34-
## current limitations
35-
36-
- Only flags are parsed, arguments are not parsed and ...args is injected at the end to catch all
37-
- Some examples of `--flags` in descriptions can throw off the regex and get included in the parsed flags
38-
- `<format>` (types) to flags are parsed, but not added to the nu shell completion type hints
39-
40-
## usage
41-
42-
generate and save source to a file
43-
44-
```nu
45-
source parse-help.nu
46-
cargo --help | parse-help | make-completion cargo | save cargo.nu
47-
```
48-
49-
## example
50-
51-
This can be saved to a file and sourced. Example of output
52-
53-
```nu
54-
extern "cargo" [
55-
--version(-V) #Print version info and exit
56-
--list #List installed commands
57-
--explain #Run `rustc --explain CODE`
58-
--verbose(-v) #Use verbose output (-vv very verbose/build.rs output)
59-
--quiet(-q) #Do not print cargo log messages
60-
--color #Coloring: auto, always, never
61-
--frozen #Require Cargo.lock and cache are up to date
62-
--locked #Require Cargo.lock is up to date
63-
--offline #Run without accessing the network
64-
--config #Override a configuration value (unstable)
65-
--help(-h) #Print help information
66-
...args
67-
]
68-
69-
extern "nu" [
70-
--help(-h) #Display this help message
71-
--stdin #redirect the stdin
72-
--login(-l) #start as a login shell
73-
--interactive(-i) #start as an interactive shell
74-
--version(-v) #print the version
75-
--perf(-p) #start and print performance metrics during startup
76-
--testbin #run internal test binary
77-
--commands(-c) #run the given commands and then exit
78-
--config #start with an alternate config file
79-
--env-config #start with an alternate environment config file
80-
--log-level #log level for performance logs
81-
--threads(-t) #threads to use for parallel commands
82-
...args
83-
]
84-
```
85-
86-
Which outputs like so on tab completion for `cargo --`
87-
```
88-
❯ | cargo --
89-
--color Coloring: auto, always, never
90-
--config Override a configuration value (unstable)
91-
--explain Run `rustc --explain CODE`
92-
--frozen Require Cargo.lock and cache are up to date
93-
--help Display this help message
94-
--help Print help information
95-
--list List installed commands
96-
--locked Require Cargo.lock is up to date
97-
--offline Run without accessing the network
98-
--quiet Do not print cargo log messages
99-
--verbose Use verbose output (-vv very verbose/build.rs output)
100-
--version Print version info and exit
101-
```
8+
Completions in this directory should still work in recent Nushell releases.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
def complete-commands [
2+
context: string
3+
] {
4+
with-env {COMP_LINE: $context} {
5+
aws_completer
6+
| lines
7+
| each {|x| $"($x) "}
8+
}
9+
}
10+
11+
export extern "aws" [
12+
...command: string@complete-commands
13+
]

custom-completions/aws/readme.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Amazon Web Services CLI completions
2+
3+
A Nushell extern definition and completers for [Amazon Web Services CLI `aws`](https://aws.amazon.com/cli/).
4+
5+
This module utilizes the `aws_completer` binary that ships with `aws` to provide completions
6+
7+
## How to use
8+
9+
Add `source path/to/aws-completions.nu` to your `config.nu` (`$nu.config-path`).

custom-completions/bat/bat-completions.nu

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# A cat(1) clone with syntax highlighting and Git integration
22
export extern "bat" [
3-
...file: path # file to print / concatenate
3+
...file: path # file(s) to print / concatenate
44
--help # Print help (see a summary with '-h')
55
-h # Print help (see more with '--help')
66
--version # Print version

custom-completions/git/git-completions.nu

Lines changed: 176 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,133 @@
1+
# nu-version: 0.102.0
2+
3+
module git-completion-utils {
4+
export const GIT_SKIPABLE_FLAGS = ['-v', '--version', '-h', '--help', '-p', '--paginate', '-P', '--no-pager', '--no-replace-objects', '--bare']
5+
6+
# Helper function to append token if non-empty
7+
def append-non-empty [token: string]: list<string> -> list<string> {
8+
if ($token | is-empty) { $in } else { $in | append $token }
9+
}
10+
11+
# Split a string to list of args, taking quotes into account.
12+
# Code is copied and modified from https://github.com/nushell/nushell/issues/14582#issuecomment-2542596272
13+
export def args-split []: string -> list<string> {
14+
# Define our states
15+
const STATE_NORMAL = 0
16+
const STATE_IN_SINGLE_QUOTE = 1
17+
const STATE_IN_DOUBLE_QUOTE = 2
18+
const STATE_ESCAPE = 3
19+
const WHITESPACES = [" " "\t" "\n" "\r"]
20+
21+
# Initialize variables
22+
mut state = $STATE_NORMAL
23+
mut current_token = ""
24+
mut result: list<string> = []
25+
mut prev_state = $STATE_NORMAL
26+
27+
# Process each character
28+
for char in ($in | split chars) {
29+
if $state == $STATE_ESCAPE {
30+
# Handle escaped character
31+
$current_token = $current_token + $char
32+
$state = $prev_state
33+
} else if $char == '\' {
34+
# Enter escape state
35+
$prev_state = $state
36+
$state = $STATE_ESCAPE
37+
} else if $state == $STATE_NORMAL {
38+
if $char == "'" {
39+
$state = $STATE_IN_SINGLE_QUOTE
40+
} else if $char == '"' {
41+
$state = $STATE_IN_DOUBLE_QUOTE
42+
} else if ($char in $WHITESPACES) {
43+
# Whitespace in normal state means token boundary
44+
$result = $result | append-non-empty $current_token
45+
$current_token = ""
46+
} else {
47+
$current_token = $current_token + $char
48+
}
49+
} else if $state == $STATE_IN_SINGLE_QUOTE {
50+
if $char == "'" {
51+
$state = $STATE_NORMAL
52+
} else {
53+
$current_token = $current_token + $char
54+
}
55+
} else if $state == $STATE_IN_DOUBLE_QUOTE {
56+
if $char == '"' {
57+
$state = $STATE_NORMAL
58+
} else {
59+
$current_token = $current_token + $char
60+
}
61+
}
62+
}
63+
# Handle the last token
64+
$result = $result | append-non-empty $current_token
65+
# Return the result
66+
$result
67+
}
68+
69+
# Get changed files which can be restored by `git checkout --`
70+
export def get-changed-files []: nothing -> list<string> {
71+
^git status -uno --porcelain=2 | lines
72+
| where $it =~ '^1 [.MD]{2}'
73+
| each { split row ' ' -n 9 | last }
74+
}
75+
76+
# Get files which can be retrieved from a branch/commit by `git checkout <tree-ish>`
77+
export def get-checkoutable-files []: nothing -> list<string> {
78+
# Relevant statuses are .M", "MM", "MD", ".D", "UU"
79+
^git status -uno --porcelain=2 | lines
80+
| where $it =~ '^1 ([.MD]{2}|UU)'
81+
| each { split row ' ' -n 9 | last }
82+
}
83+
84+
export def get-all-git-branches []: nothing -> list<string> {
85+
^git branch -a --format '%(refname:lstrip=2)%09%(upstream:lstrip=2)' | lines | str trim | filter { not ($in ends-with 'HEAD' ) }
86+
}
87+
88+
# Extract remote branches which do not have local counterpart
89+
export def extract-remote-branches-nonlocal-short [current: string]: list<string> -> list<string> {
90+
# Input is a list of lines, like:
91+
# ╭────┬────────────────────────────────────────────────╮
92+
# │ 0 │ feature/awesome-1 origin/feature/awesome-1 │
93+
# │ 1 │ fix/bug-1 origin/fix/bug-1 │
94+
# │ 2 │ main origin/main │
95+
# │ 3 │ origin/HEAD │
96+
# │ 4 │ origin/feature/awesome-1 │
97+
# │ 5 │ origin/fix/bug-1 │
98+
# │ 6 │ origin/feature/awesome-2 │
99+
# │ 7 │ origin/main │
100+
# │ 8 │ upstream/main │
101+
# │ 9 │ upstream/awesome-3 │
102+
# ╰────┴────────────────────────────────────────────────╯
103+
# and we pick ['feature/awesome-2', 'awesome-3']
104+
let lines = $in
105+
let long_current = if ($current | is-empty) { '' } else { $'origin/($current)' }
106+
let branches = $lines | filter { ($in != $long_current) and not ($in starts-with $"($current)\t") }
107+
let tracked_remotes = $branches | find --no-highlight "\t" | each { split row "\t" -n 2 | get 1 }
108+
let floating_remotes = $lines | filter { "\t" not-in $in and $in not-in $tracked_remotes }
109+
$floating_remotes | each {
110+
let v = $in | split row -n 2 '/' | get 1
111+
if $v == $current { null } else $v
112+
}
113+
}
114+
115+
export def extract-mergable-sources [current: string]: list<string> -> list<record<value: string, description: string>> {
116+
let lines = $in
117+
let long_current = if ($current | is-empty) { '' } else { $'origin/($current)' }
118+
let branches = $lines | filter { ($in != $long_current) and not ($in starts-with $"($current)\t") }
119+
let git_table: list<record<n: string, u: string>> = $branches | each {|v| if "\t" in $v { $v | split row "\t" -n 2 | {n: $in.0, u: $in.1 } } else {n: $v, u: null } }
120+
let siblings = $git_table | where u == null and n starts-with 'origin/' | get n | str substring 7..
121+
let remote_branches = $git_table | filter {|r| $r.u == null and not ($r.n starts-with 'origin/') } | get n
122+
[...($siblings | wrap value | insert description Local), ...($remote_branches | wrap value | insert description Remote)]
123+
}
124+
125+
# Get local branches, remote branches which can be passed to `git merge`
126+
export def get-mergable-sources []: nothing -> list<record<value: string, description: string>> {
127+
let current = (^git branch --show-current) # Can be empty if in detached HEAD
128+
(get-all-git-branches | extract-mergable-sources $current)
129+
}
130+
}
1131

2132
def "nu-complete git available upstream" [] {
3133
^git branch --no-color -a | lines | each { |line| $line | str replace '* ' "" | str trim }
@@ -32,56 +162,53 @@ def "nu-complete git remote branches with prefix" [] {
32162
^git branch --no-color -r | lines | parse -r '^\*?(\s*|\s*\S* -> )(?P<branch>\S*$)' | get branch | uniq
33163
}
34164

35-
# Yield remote branches *without* prefix which do not have a local counterpart.
36-
# E.g. `upstream/feature-a` as `feature-a` to checkout and track in one command
37-
# with `git checkout` or `git switch`.
38-
def "nu-complete git remote branches nonlocal without prefix" [] {
39-
# Get regex to strip remotes prefixes. It will look like `(origin|upstream)`
40-
# for the two remotes `origin` and `upstream`.
41-
let remotes_regex = (["(", ((nu-complete git remotes | each {|r| [$r, '/'] | str join}) | str join "|"), ")"] | str join)
42-
let local_branches = (nu-complete git local branches)
43-
^git branch --no-color -r | lines | parse -r (['^[\* ]+', $remotes_regex, '?(?P<branch>\S+)'] | flatten | str join) | get branch | uniq | where {|branch| $branch != "HEAD"} | where {|branch| $branch not-in $local_branches }
44-
}
45-
46165
# Yield local and remote branch names which can be passed to `git merge`
47166
def "nu-complete git mergable sources" [] {
48-
let current = (^git branch --show-current)
49-
let long_current = $'origin/($current)'
50-
let git_table = ^git branch -a --format '%(refname:lstrip=2)%09%(upstream:lstrip=2)' | lines | str trim | where { ($in != $long_current) and not ($in starts-with $"($current)\t") and not ($in ends-with 'HEAD') } | each {|v| if "\t" in $v { $v | split row "\t" -n 2 | {'n': $in.0, 'u': $in.1 } } else {'n': $v, 'u': null } }
51-
let siblings = $git_table | where u == null and n starts-with 'origin/' | get n | str substring 7..
52-
let remote_branches = $git_table | filter {|r| $r.u == null and not ($r.n starts-with 'origin/') } | get n
53-
[...($siblings | wrap value | insert description Local), ...($remote_branches | wrap value | insert description Remote)]
167+
use git-completion-utils *
168+
(get-mergable-sources)
54169
}
55170

56171
def "nu-complete git switch" [] {
57-
(nu-complete git local branches)
58-
| parse "{value}"
59-
| insert description "local branch"
60-
| append (nu-complete git remote branches nonlocal without prefix
61-
| parse "{value}"
62-
| insert description "remote branch")
172+
use git-completion-utils *
173+
let current = (^git branch --show-current) # Can be empty if in detached HEAD
174+
let local_branches = ^git branch --format '%(refname:short)' | lines | filter { $in != $current } | wrap value | insert description 'Local branch'
175+
let remote_branches = (get-all-git-branches | extract-remote-branches-nonlocal-short $current) | wrap value | insert description 'Remote branch'
176+
[...$local_branches, ...$remote_branches]
63177
}
64178

65-
def "nu-complete git checkout" [] {
66-
let table_of_checkouts = (nu-complete git local branches)
67-
| parse "{value}"
68-
| insert description "local branch"
69-
| append (nu-complete git remote branches nonlocal without prefix
70-
| parse "{value}"
71-
| insert description "remote branch")
72-
| append (nu-complete git remote branches with prefix
73-
| parse "{value}"
74-
| insert description "remote branch")
75-
| append (nu-complete git files | where description != "Untracked" | select value | insert description "git file")
76-
| append (nu-complete git commits all)
77-
78-
return {
179+
def "nu-complete git checkout" [context: string, position?:int] {
180+
use git-completion-utils *
181+
let preceding = $context | str substring ..$position
182+
# See what user typed before, like 'git checkout a-branch a-path'.
183+
# We exclude some flags from previous tokens, to detect if a branch name has been used as the first argument.
184+
# FIXME: This method is still naive, though.
185+
let prev_tokens = $preceding | str trim | args-split | where ($it not-in $GIT_SKIPABLE_FLAGS)
186+
# In these scenarios, we suggest only file paths, not branch:
187+
# - After '--'
188+
# - First arg is a branch
189+
# If before '--' is just 'git checkout' (or its alias), we suggest "dirty" files only (user is about to reset file).
190+
if $prev_tokens.2? == '--' {
191+
return (get-changed-files)
192+
}
193+
if '--' in $prev_tokens {
194+
return (get-checkoutable-files)
195+
}
196+
# Already typed first argument.
197+
if ($prev_tokens | length) > 2 and $preceding ends-with ' ' {
198+
return (get-checkoutable-files)
199+
}
200+
# The first argument can be local branches, remote branches, files and commits
201+
# Get local and remote branches
202+
let branches = (get-mergable-sources) | insert style {|row| if $row.description == 'Local' { 'blue' } else 'blue_italic' } | update description { $in + ' branch' }
203+
let files = (get-checkoutable-files) | wrap value | insert description 'File' | insert style green
204+
let commits = ^git rev-list -n 400 --remotes --oneline | lines | split column -n 2 ' ' value description | insert style light_cyan_dimmed
205+
{
79206
options: {
80207
case_sensitive: false,
81208
completion_algorithm: prefix,
82209
sort: false,
83210
},
84-
completions: $table_of_checkouts
211+
completions: [...$branches, ...$files, ...$commits]
85212
}
86213
}
87214

@@ -143,7 +270,7 @@ def "nu-complete git files" [] {
143270
def "nu-complete git built-in-refs" [] {
144271
[HEAD FETCH_HEAD ORIG_HEAD]
145272
}
146-
273+
147274
def "nu-complete git refs" [] {
148275
nu-complete git local branches
149276
| parse "{value}"
@@ -836,5 +963,14 @@ export extern "git grep" [
836963
]
837964

838965
export extern "git" [
839-
command?: string@"nu-complete git subcommands" # subcommands
966+
command?: string@"nu-complete git subcommands" # Subcommands
967+
--version(-v) # Prints the Git suite version that the git program came from
968+
--help(-h) # Prints the synopsis and a list of the most commonly used commands
969+
--html-path # Print the path, without trailing slash, where Git’s HTML documentation is installed and exit
970+
--man-path # Print the manpath (see man(1)) for the man pages for this version of Git and exit
971+
--info-path # Print the path where the Info files documenting this version of Git are installed and exit
972+
--paginate(-p) # Pipe all output into less (or if set, $env.PAGER) if standard output is a terminal
973+
--no-pager(-P) # Do not pipe Git output into a pager
974+
--no-replace-objects # Do not use replacement refs to replace Git objects
975+
--bare # Treat the repository as a bare repository
840976
]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# komorebi
2+
3+
[`komorebi`](https://github.com/LGUG2Z/komorebi) is a tiling window manager for Windows! It allows you to control application windows, virtual workspaces, and display monitors, with a CLI that works with third-party software like [`whkd`](https://github.com/LGUG2Z/whkd) and [AutoHotkey](https://github.com/AutoHotkey/AutoHotkey).

0 commit comments

Comments
 (0)