Module: Space::Core::ShellIntegration
- Defined in:
- lib/space_core/shell_integration.rb
Constant Summary collapse
- FISH_TEMPLATE =
"# Generated by space-architect. Do not edit by hand.\n\nfunction __space_architect_command\n set -l __ps_index 1\n\n while test $__ps_index -le (count $argv)\n set -l __ps_arg $argv[$__ps_index]\n\n switch \"$__ps_arg\"\n case \"--\"\n set __ps_index (math $__ps_index + 1)\n if test $__ps_index -le (count $argv)\n echo $argv[$__ps_index]\n end\n return 0\n case \"--color\" \"--colors\"\n set __ps_index (math $__ps_index + 2)\n continue\n case \"--color=*\" \"--colors=*\"\n set __ps_index (math $__ps_index + 1)\n continue\n case \"-*\"\n return 0\n case \"*\"\n echo $__ps_arg\n return 0\n end\n end\nend\n\nfunction __space_architect_has_color_option\n set -l __ps_index 1\n\n while test $__ps_index -le (count $argv)\n set -l __ps_arg $argv[$__ps_index]\n\n switch \"$__ps_arg\"\n case \"--color\" \"--colors\" \"--color=*\" \"--colors=*\"\n return 0\n case \"--\"\n return 1\n end\n\n set __ps_index (math $__ps_index + 1)\n end\n\n return 1\nend\n\nfunction space --wraps space --description \"Create and manage project spaces\"\n if not set -q __space_architect_compat_checked\n set -g __space_architect_compat_checked 1\n set -l __space_architect_installed_version __SPACE_ARCHITECT_VERSION__\n set -l __space_architect_binary_version (command space --version 2>/dev/null)\n if test \"$__space_architect_binary_version\" != \"$__space_architect_installed_version\"\n echo \"space-architect: shell integration version $__space_architect_installed_version does not match binary version $__space_architect_binary_version; re-run 'space shell fish install'\" >&2\n end\n end\n\n set -l __space_command (__space_architect_command $argv)\n set -l __space_args $argv\n\n if test -t 1; and not __space_architect_has_color_option $argv\n set __space_args --color=always $__space_args\n end\n\n switch \"$__space_command\"\n case new use\n set -l __space_output (command space $__space_args)\n set -l __space_status $status\n\n if test (count $__space_output) -gt 0\n printf \"%s\\n\" $__space_output\n end\n\n if test $__space_status -eq 0\n set -l __space_target $__space_output[-1]\n set __space_target (string replace -r \"^~(?=/|\\$)\" $HOME -- $__space_target)\n if test -d \"$__space_target\"\n cd \"$__space_target\"\n end\n end\n\n return $__space_status\n case \"*\"\n command space $__space_args\n return $status\n end\nend\n"- FISH_COMPLETIONS =
"# Generated by space-architect. Do not edit by hand.\n\nfunction __space_architect_complete_command\n set -l tokens (commandline -opc)\n set -l index 2\n\n while test $index -le (count $tokens)\n set -l token $tokens[$index]\n\n switch \"$token\"\n case \"--\"\n set index (math $index + 1)\n if test $index -le (count $tokens)\n echo $tokens[$index]\n end\n return 0\n case \"--color\" \"--colors\"\n set index (math $index + 2)\n continue\n case \"--color=*\" \"--colors=*\"\n set index (math $index + 1)\n continue\n case \"-*\"\n set index (math $index + 1)\n continue\n case \"*\"\n echo $token\n return 0\n end\n end\nend\n\nfunction __space_architect_complete_needs_command\n test -z \"$(__space_architect_complete_command)\"\nend\n\nfunction __space_architect_complete_using_command\n contains -- (__space_architect_complete_command) $argv\nend\n\nfunction __space_architect_complete_first_argument_after\n set -l commands $argv\n set -l tokens (commandline -opc)\n set -l index 2\n set -l matched_command 0\n\n while test $index -le (count $tokens)\n set -l token $tokens[$index]\n\n switch \"$token\"\n case \"--color\" \"--colors\"\n set index (math $index + 2)\n continue\n case \"--color=*\" \"--colors=*\" \"-*\"\n set index (math $index + 1)\n continue\n end\n\n if test $matched_command -eq 0\n if contains -- \"$token\" $commands\n set matched_command 1\n else\n return 1\n end\n else\n echo $token\n return 0\n end\n\n set index (math $index + 1)\n end\n\n return 1\nend\n\nfunction __space_architect_complete_has_first_argument_after\n set -q argv[1]; or return 1\n set -l first_argument (__space_architect_complete_first_argument_after $argv)\n test -n \"$first_argument\"\nend\n\nfunction __space_architect_complete_second_argument_after\n set -q argv[1]; or return 1\n set -l command $argv[1]\n set -l tokens (commandline -opc)\n set -l index 2\n set -l matched_command 0\n set -l matched_first_argument 0\n\n while test $index -le (count $tokens)\n set -l token $tokens[$index]\n\n switch \"$token\"\n case \"--color\" \"--colors\"\n set index (math $index + 2)\n continue\n case \"--color=*\" \"--colors=*\" \"-*\"\n set index (math $index + 1)\n continue\n end\n\n if test $matched_command -eq 0\n test \"$token\" = \"$command\"; or return 1\n set matched_command 1\n else if test $matched_first_argument -eq 0\n set matched_first_argument 1\n else\n echo $token\n return 0\n end\n\n set index (math $index + 1)\n end\n\n return 1\nend\n\nfunction __space_architect_complete_has_second_argument_after\n set -q argv[1]; or return 1\n set -l second_argument (__space_architect_complete_second_argument_after $argv)\n test -n \"$second_argument\"\nend\n\nfunction __space_architect_complete_first_argument_is\n set -q argv[1]; or return 1\n set -l expected $argv[1]\n set -e argv[1]\n test \"$(__space_architect_complete_first_argument_after $argv)\" = \"$expected\"\nend\n\nfunction __space_architect_complete_spaces\n command space shell complete spaces 2>/dev/null\nend\n\nfunction __space_architect_complete_statuses\n command space shell complete statuses 2>/dev/null\nend\n\nfunction __space_architect_complete_config_keys\n command space shell complete config-keys 2>/dev/null\nend\n\nfunction __space_architect_complete_config_set_key\n set -l tokens (commandline -opc)\n set -l index 2\n set -l matched_config 0\n set -l matched_set 0\n\n while test $index -le (count $tokens)\n set -l token $tokens[$index]\n\n switch \"$token\"\n case \"--color\" \"--colors\"\n set index (math $index + 2)\n continue\n case \"--color=*\" \"--colors=*\" \"-*\"\n set index (math $index + 1)\n continue\n end\n\n if test $matched_config -eq 0\n test \"$token\" = \"config\"; or return 1\n set matched_config 1\n else if test $matched_set -eq 0\n test \"$token\" = \"set\"; or return 1\n set matched_set 1\n else\n echo $token\n return 0\n end\n\n set index (math $index + 1)\n end\n\n return 1\nend\n\nfunction __space_architect_complete_config_set_has_key\n test -n \"$(__space_architect_complete_config_set_key)\"\nend\n\nfunction __space_architect_complete_config_set_key_is\n test \"$(__space_architect_complete_config_set_key)\" = \"$argv[1]\"\nend\n\ncomplete -c space -f -l color -x -a \"auto always never\" -d \"Color output\"\ncomplete -c space -f -l colors -x -a \"auto always never\" -d \"Color output\"\ncomplete -c space -f -n \"__space_architect_complete_using_command init shell\" -l force -d \"Overwrite existing files\"\ncomplete -c space -f -n \"__space_architect_complete_using_command new\" -s r -l repo -x -d \"Clone a repo into the new space\"\n\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a init -d \"Create default XDG config and state files\"\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a new -d \"Create a new project space\"\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a list -d \"List spaces\"\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a ls -d \"List spaces\"\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a show -d \"Show space metadata\"\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a path -d \"Print a space path\"\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a use -d \"Select and cd to a space with fish integration\"\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a current -d \"Show the current space\"\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a status -d \"Report or set a space status\"\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a config -d \"Show or update config\"\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a repo -d \"Manage repos in the current space\"\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a repos -d \"Manage repos in the current space\"\ncomplete -c space -f -n \"__space_architect_complete_needs_command\" -a shell -d \"Manage shell integration\"\n\ncomplete -c space -f -n \"__space_architect_complete_using_command show path use\" -a \"(__space_architect_complete_spaces)\" -d \"Space\"\ncomplete -c space -f -n \"__space_architect_complete_using_command status\" -a \"(__space_architect_complete_spaces)\" -d \"Space\"\ncomplete -c space -f -n \"__space_architect_complete_using_command status\" -a \"(__space_architect_complete_statuses)\" -d \"Status\"\ncomplete -c space -f -n \"__space_architect_complete_first_argument_is init shell; and not __space_architect_complete_has_second_argument_after shell\" -a fish -d \"Fish shell\"\n\ncomplete -c space -f -n \"__space_architect_complete_using_command repo repos; and not __space_architect_complete_has_first_argument_after repo repos\" -a add -d \"Clone repos into the current space\"\ncomplete -c space -f -n \"__space_architect_complete_using_command repo repos; and not __space_architect_complete_has_first_argument_after repo repos\" -a list -d \"List repos in the current space\"\ncomplete -c space -f -n \"__space_architect_complete_using_command repo repos; and not __space_architect_complete_has_first_argument_after repo repos\" -a ls -d \"List repos in the current space\"\ncomplete -c space -f -n \"__space_architect_complete_using_command repo repos; and not __space_architect_complete_has_first_argument_after repo repos\" -a resolve -d \"Resolve repo names without cloning\"\n\ncomplete -c space -f -n \"__space_architect_complete_using_command config; and not __space_architect_complete_has_first_argument_after config\" -a show -d \"Show config\"\ncomplete -c space -f -n \"__space_architect_complete_using_command config; and not __space_architect_complete_has_first_argument_after config\" -a path -d \"Print config path\"\ncomplete -c space -f -n \"__space_architect_complete_using_command config; and not __space_architect_complete_has_first_argument_after config\" -a set -d \"Set a config value\"\ncomplete -c space -f -n \"__space_architect_complete_first_argument_is set config; and not __space_architect_complete_config_set_has_key\" -a \"(__space_architect_complete_config_keys)\" -d \"Config key\"\ncomplete -c space -f -n \"__space_architect_complete_config_set_key_is git_clone_protocol\" -a \"ssh https\" -d \"Clone protocol\"\ncomplete -c space -f -n \"__space_architect_complete_config_set_key_is default_provider\" -a \"github.com gitlab.com\" -d \"Git provider\"\n\ncomplete -c space -f -n \"__space_architect_complete_using_command shell; and not __space_architect_complete_has_first_argument_after shell\" -a init -d \"Print shell integration\"\ncomplete -c space -f -n \"__space_architect_complete_using_command shell; and not __space_architect_complete_has_first_argument_after shell\" -a fish -d \"Manage fish integration and completions\"\ncomplete -c space -f -n \"__space_architect_complete_using_command shell; and not __space_architect_complete_has_first_argument_after shell\" -a complete -d \"Print completion candidates\"\ncomplete -c space -f -n \"__space_architect_complete_first_argument_is fish shell; and not __space_architect_complete_has_second_argument_after shell\" -a install -d \"Install fish integration and completions\"\ncomplete -c space -f -n \"__space_architect_complete_first_argument_is fish shell; and not __space_architect_complete_has_second_argument_after shell\" -a uninstall -d \"Remove fish integration and completions\"\ncomplete -c space -f -n \"__space_architect_complete_first_argument_is fish shell; and not __space_architect_complete_has_second_argument_after shell\" -a path -d \"Print fish integration paths\"\ncomplete -c space -f -n \"__space_architect_complete_first_argument_is complete shell; and not __space_architect_complete_has_second_argument_after shell\" -a \"spaces statuses config-keys config-values shells color-modes repo-subcommands config-subcommands fish-subcommands\" -d \"Completion kind\"\n"
Class Method Summary collapse
- .completions_for(shell) ⇒ Object
- .completions_path_for(shell, env: ENV) ⇒ Object
- .for(shell) ⇒ Object
- .install(shell, env: ENV, force: false) ⇒ Object
- .managed_fish?(content) ⇒ Boolean
- .path_for(shell, env: ENV) ⇒ Object
- .remove_managed_file(path:, content:, force:, description:) ⇒ Object
- .uninstall(shell, env: ENV, force: false) ⇒ Object
- .write_managed_file(path:, content:, force:, description:) ⇒ Object
Class Method Details
.completions_for(shell) ⇒ Object
339 340 341 342 343 344 345 346 |
# File 'lib/space_core/shell_integration.rb', line 339 def self.completions_for(shell) case shell.to_s when "fish" FISH_COMPLETIONS else raise Error, "Unsupported shell '#{shell}'. Expected: fish" end end |
.completions_path_for(shell, env: ENV) ⇒ Object
357 358 359 360 361 362 363 364 |
# File 'lib/space_core/shell_integration.rb', line 357 def self.completions_path_for(shell, env: ENV) case shell.to_s when "fish" XDG.config_home(env: env).join("fish", "completions", "space.fish") else raise Error, "Unsupported shell '#{shell}'. Expected: fish" end end |
.for(shell) ⇒ Object
330 331 332 333 334 335 336 337 |
# File 'lib/space_core/shell_integration.rb', line 330 def self.for(shell) case shell.to_s when "fish" FISH_TEMPLATE.gsub("__SPACE_ARCHITECT_VERSION__", VERSION) else raise Error, "Unsupported shell '#{shell}'. Expected: fish" end end |
.install(shell, env: ENV, force: false) ⇒ Object
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/space_core/shell_integration.rb', line 366 def self.install(shell, env: ENV, force: false) function_result = write_managed_file( path: path_for(shell, env:), content: self.for(shell), force: force, description: "fish function" ) completions_result = write_managed_file( path: completions_path_for(shell, env:), content: completions_for(shell), force: force, description: "fish completions" ) function_result.merge( completions_action: completions_result.fetch(:action), completions_path: completions_result.fetch(:path) ) end |
.managed_fish?(content) ⇒ Boolean
406 407 408 409 |
# File 'lib/space_core/shell_integration.rb', line 406 def self.managed_fish?(content) content.include?("Generated by space-architect") || (content.include?("function __space_architect_command") && content.include?("function space --wraps space")) end |
.path_for(shell, env: ENV) ⇒ Object
348 349 350 351 352 353 354 355 |
# File 'lib/space_core/shell_integration.rb', line 348 def self.path_for(shell, env: ENV) case shell.to_s when "fish" XDG.config_home(env: env).join("fish", "functions", "space.fish") else raise Error, "Unsupported shell '#{shell}'. Expected: fish" end end |
.remove_managed_file(path:, content:, force:, description:) ⇒ Object
426 427 428 429 430 431 432 433 434 435 436 |
# File 'lib/space_core/shell_integration.rb', line 426 def self.remove_managed_file(path:, content:, force:, description:) return { action: :missing, path: path } unless path.exist? existing = path.read if existing != content && !force && !managed_fish?(existing) raise Error, "Refusing to remove existing #{description} at #{path}. Re-run with --force." end FileUtils.rm_f(path) { action: :removed, path: path } end |
.uninstall(shell, env: ENV, force: false) ⇒ Object
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
# File 'lib/space_core/shell_integration.rb', line 386 def self.uninstall(shell, env: ENV, force: false) function_result = remove_managed_file( path: path_for(shell, env:), content: self.for(shell), force: force, description: "fish function" ) completions_result = remove_managed_file( path: completions_path_for(shell, env:), content: completions_for(shell), force: force, description: "fish completions" ) function_result.merge( completions_action: completions_result.fetch(:action), completions_path: completions_result.fetch(:path) ) end |
.write_managed_file(path:, content:, force:, description:) ⇒ Object
411 412 413 414 415 416 417 418 419 420 421 422 423 424 |
# File 'lib/space_core/shell_integration.rb', line 411 def self.write_managed_file(path:, content:, force:, description:) existing = path.read if path.exist? if existing && existing != content && !force && !managed_fish?(existing) raise Error, "Refusing to overwrite existing #{description} at #{path}. Re-run with --force." end if existing == content { action: :unchanged, path: path } else AtomicWrite.write(path, content) { action: existing ? :updated : :installed, path: path } end end |