diff --git a/.gitignore b/.gitignore index aa96700..2c1ed47 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ .zed .vscode -nushell/cache/* -!nushell/cache/.gitignore diff --git a/nushell/cache/.gitignore b/nushell/cache/.gitignore index c96a04f..0245679 100644 --- a/nushell/cache/.gitignore +++ b/nushell/cache/.gitignore @@ -1,2 +1,3 @@ * -!.gitignore \ No newline at end of file +!.gitignore +!noop.nu \ No newline at end of file diff --git a/nushell/cache/noop.nu b/nushell/cache/noop.nu new file mode 100644 index 0000000..5442d62 --- /dev/null +++ b/nushell/cache/noop.nu @@ -0,0 +1 @@ +# Fallback completion module intentionally exports nothing. diff --git a/nushell/modules/pj_completions.nu b/nushell/modules/pj_completions.nu index aa61f07..8bb317c 100644 --- a/nushell/modules/pj_completions.nu +++ b/nushell/modules/pj_completions.nu @@ -1,6 +1,14 @@ const pj_module_dir = (path self | path dirname) -const pj_completion_base_dir = ($pj_module_dir | path join '..' 'cache' 'nu_scripts' 'custom-completions') -const pj_completion_commands = [git ssh cargo uv rustup make pytest rg tar fzf vscode winget zig] +const pj_cache_dir = ($pj_module_dir | path join '..' 'cache') +const pj_completion_base_dir = ($pj_cache_dir | path join 'nu_scripts' 'custom-completions') +const pj_completion_commands = [git ssh cargo uv rustup make pytest rg tar vscode winget zig] +const pj_completion_noop_module = ($pj_cache_dir | path join 'noop.nu') +const pj_completion_registry_module = ($pj_cache_dir | path join 'pj_completions_registry.nu') +const pj_completion_bootstrap_module = if ($pj_completion_registry_module | path exists) { + $pj_completion_registry_module +} else { + $pj_completion_noop_module +} def _pj_completion_script_path [name: string] { ($pj_completion_base_dir | path join $name $"($name)-completions.nu") @@ -15,10 +23,78 @@ def _pj_required_completion_files [] { } } +def _pj_completion_registry_lines [] { + let header = [ + "# Auto-generated by `pj completion sync`." + "# Edit pj_completion_commands in pj_completions.nu, then re-run sync." + "const pj_registry_dir = (path self | path dirname)" + "const pj_completion_base_dir = ($pj_registry_dir | path join 'nu_scripts' 'custom-completions')" + "const pj_completion_noop_module = ($pj_registry_dir | path join 'noop.nu')" + "" + ] + + let lines = ($pj_completion_commands | each {|name| + [ + ( + "export use (if ((($pj_completion_base_dir | path join '" + + $name + + "' '" + + $name + + "-completions.nu') | path exists)) { ($pj_completion_base_dir | path join '" + + $name + + "' '" + + $name + + "-completions.nu') } else { $pj_completion_noop_module }) *" + ) + "" + ] + } | flatten) + + ($header | append $lines) +} + +def _pj_completion_help [] { + print "pj completion commands:" + print " pj completion Clone/update cache and check required completion files." + print " pj completion -u Update cached nu_scripts repository." + print " pj completion -f Force re-clone cached nu_scripts repository." + print " pj completion sync Regenerate cache registry and restart Nushell." + print " pj completion -s Same as `pj completion sync`." + print " pj completion -h Show this help message." +} + +export def "pj completion sync" [ + --help(-h) +] { + if $help { + _pj_completion_help + return + } + + mkdir $pj_cache_dir + let content = ((_pj_completion_registry_lines) | str join "\n") + $content | save -f $pj_completion_registry_module + print $"[pj completion] synced: ($pj_completion_registry_module)" + print "[pj completion] restarting Nushell..." + exec nu +} + export def "pj completion" [ --update(-u) # Pull latest changes when repo already exists. --force(-f) # Re-clone even when repo already exists. + --sync(-s) # Regenerate static registry and restart Nushell. + --help(-h) # Show help. ] { + if $help { + _pj_completion_help + return + } + + if $sync { + pj completion sync + return + } + let repo_url = "https://github.com/nushell/nu_scripts.git" let cache_dir = if ('NU_POLYJUICE_PATH' in $env) { ($env.NU_POLYJUICE_PATH | path join 'cache') @@ -94,18 +170,19 @@ export-env { } } } + + if not ($pj_completion_registry_module | path exists) { + mkdir $pj_cache_dir + let content = ((_pj_completion_registry_lines) | str join "\n") + $content | save -f $pj_completion_registry_module + + if (($env.PJ_COMPLETION_BOOTSTRAPPED? | default "0") != "1") { + load-env { PJ_COMPLETION_BOOTSTRAPPED: "1" } + print "[pj completion] generated cache registry, restarting Nushell..." + exec nu + } + } } -# Re-export imported extern signatures so they are visible when this module is `use`d. -export use ($pj_completion_base_dir | path join 'git' 'git-completions.nu') * -export use ($pj_completion_base_dir | path join 'ssh' 'ssh-completions.nu') * -export use ($pj_completion_base_dir | path join 'cargo' 'cargo-completions.nu') * -export use ($pj_completion_base_dir | path join 'uv' 'uv-completions.nu') * -export use ($pj_completion_base_dir | path join 'rustup' 'rustup-completions.nu') * -export use ($pj_completion_base_dir | path join 'make' 'make-completions.nu') * -export use ($pj_completion_base_dir | path join 'pytest' 'pytest-completions.nu') * -export use ($pj_completion_base_dir | path join 'rg' 'rg-completions.nu') * -export use ($pj_completion_base_dir | path join 'tar' 'tar-completions.nu') * -export use ($pj_completion_base_dir | path join 'vscode' 'vscode-completions.nu') * -export use ($pj_completion_base_dir | path join 'winget' 'winget-completions.nu') * -export use ($pj_completion_base_dir | path join 'zig' 'zig-completions.nu') * +# Re-export completion externs from generated static registry. +export use $pj_completion_bootstrap_module *