tabry 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 53cb186e419ee3ddbecddaf09ac32b39d93d5668c58fd81bc8d08ff16e1b168d
4
- data.tar.gz: c5d7fa4e944df15ff727eb0a9d38e2550da6988bdcf83f2dbaa743252f3c9669
3
+ metadata.gz: 87fa1708b1efb9ef81588017419bb6c63455ee786870f882783cf59f22ea462b
4
+ data.tar.gz: f0822419f2a36d48148cf7cf0ecdbd195666e2c5fe284d2e8dd6a563976c0842
5
5
  SHA512:
6
- metadata.gz: 1da3914992fd9ca409800f0183992fe6a742f0d55f04573e20c119cace1b00538294113c675a8281ff881703cbb13fb5a1802d4d164d9343dd4d5543cd9f2ca5
7
- data.tar.gz: 6a9797aaf76219131bcb3a6faa780ebedd0cd7971ad98f91e0d9f56d3d3302f4c29b62c9c4db0025fea4a1fea9047a40e54bf55400d2de1a7837915ddb7edc06
6
+ metadata.gz: de752dc58cefc4cc1caed94a4f0ae34758fdb40a9973f48ed5471b17fef517b0eecfbfd7e3735179793cce8d16d739d2cb2fe6d833c3f765f5c57e353dac1b7a
7
+ data.tar.gz: 3e26e31d951fbc7f076b3c6e5b2c96eccfd1287c5469f84447ec549dc6aca51746dc193cbed36276b2e81dab67ce2bee8204cc0e8bb6b4010a07b284bac75f32
data/bin/tabry-fish ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Run by the tabry_fish.sh fish tab completion function to plug into Tabry
5
+ # to get completion options.
6
+ # Fish-specific entrypoint
7
+
8
+ require_relative "../lib/tabry/shells/fish/wrapper"
9
+ Tabry::Fish::Wrapper.run(*ARGV)
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/tabry/cli/all_in_one"
4
+ require_relative "../lib/tabry/shells/fish"
5
+
6
+ Tabry::CLI::AllInOne.run do
7
+ config(names_underscores_to_dashes: true) do
8
+ desc <<~DESC
9
+ Generates fish completion for the tabry relative to this script
10
+ for the given command name and tabry JSON/YML file. Generates
11
+ fish functions unique to the command name to avoid conflicting with
12
+ other potential tabry installations.
13
+ DESC
14
+ arg :command_name, "Name of the command, e.g. 'mycli'"
15
+ arg :tabry_json_path, "Path to the mycli.json or mycli.yml compiled tabry file"
16
+ flagarg "uniq-fn-id,i", <<~DESC
17
+ Unique identifier to use for the unique tabry completion bash functions
18
+ (default is the capitalized command name)
19
+ DESC
20
+ end
21
+
22
+ def main
23
+ puts Tabry::Shells::Fish.generate(
24
+ args.command_name,
25
+ args.tabry_json_path,
26
+ uniq_fn_id: flags.uniq_fn_id,
27
+ )
28
+ end
29
+ end
30
+
31
+
@@ -25,7 +25,7 @@ module Tabry
25
25
 
26
26
  # Hack to avoid processing block any more if only running completion
27
27
  # That way you an have expensive requires after the include
28
- if (ARGV.first == "completion") && ARGV.length == 3 && ARGV[2].to_s =~ /^[0-9]+$/
28
+ if ((ARGV.first == "completion")) && ARGV.length == 3 && ARGV[2].to_s =~ /^[0-9]+$/
29
29
  throw :run_completion, true
30
30
  end
31
31
  end
@@ -45,14 +45,26 @@ module Tabry
45
45
 
46
46
  def self.define_completion_methods(cli_class, config, cmd_name: nil)
47
47
  cli_class.module_eval do
48
+
48
49
  define_method :completion__bash do
49
50
  require_relative "../shells/bash"
50
51
  Kernel.puts Tabry::Shells::Bash.generate_self(cmd_name: cmd_name)
51
52
  end
52
53
 
54
+ define_method :completion__fish do
55
+ require_relative "../shells/fish"
56
+ Kernel.puts Tabry::Shells::Fish.generate_self(cmd_name: cmd_name)
57
+ end
58
+
53
59
  define_method :completion do
54
- require_relative "../shells/bash/wrapper"
55
- Tabry::Bash::Wrapper.run(args.cmd_line, args.comp_point, config: config)
60
+ fish_mode = ENV.fetch("TABRY_FISH_MODE", false)
61
+ if fish_mode
62
+ require_relative "../shells/fish/wrapper"
63
+ Tabry::Fish::Wrapper.run(args.cmd_line, args.comp_point, config: config)
64
+ else
65
+ require_relative "../shells/bash/wrapper"
66
+ Tabry::Bash::Wrapper.run(args.cmd_line, args.comp_point, config: config)
67
+ end
56
68
  end
57
69
  end
58
70
  end
@@ -77,13 +89,22 @@ module Tabry
77
89
  # If we recognize command is going to be a completion command, fast track and
78
90
  # run completion now
79
91
  if run_completion
80
- require_relative "../shells/bash/wrapper"
81
- Tabry::Bash::Wrapper.run(ARGV[1], ARGV[2], config: config)
92
+ if ARGV.first == "completion"
93
+ fish_mode = ENV.fetch("TABRY_FISH_MODE", false)
94
+ if fish_mode
95
+ require_relative "../shells/fish/wrapper"
96
+ Tabry::Fish::Wrapper.run(ARGV[1], ARGV[2], config: config)
97
+ else
98
+ require_relative "../shells/bash/wrapper"
99
+ Tabry::Bash::Wrapper.run(ARGV[1], ARGV[2], config: config)
100
+ end
101
+ exit
102
+ end
82
103
  end
83
104
 
84
105
  # If we recognize there is a "completion" subcommand, add completion
85
106
  # methods -- if not already defined by caller in the block
86
- if config.main.subs.by_name["completion"] && !cli.instance_methods.include?(:completion__bash)
107
+ if config.main.subs.by_name["completion"] && !cli.instance_methods.include?(:completion__bash) && !cli.instance_methods.include?(:completion__fish)
87
108
  define_completion_methods(cli, config)
88
109
  end
89
110
 
@@ -24,6 +24,7 @@ module Tabry
24
24
  sub :completion do
25
25
  desc "Get tab completion shell config"
26
26
  sub :bash, "Get tab completion for bash or zsh"
27
+ sub :fish, "Get tab completion for fish"
27
28
  arg :cmd_line, "(for internal usage, when used instead of subcommand) full command line for getting completion options"
28
29
  arg :comp_point, "(for internal usage, when used instead of subcommand) comp point"
29
30
  end
@@ -5,7 +5,7 @@ require_relative "option_base"
5
5
  module Tabry
6
6
  module Models
7
7
  class ConstOption < OptionBase
8
- def options(token)
8
+ def options(token, _params)
9
9
  if value.start_with?(token)
10
10
  [value]
11
11
  else
@@ -16,10 +16,14 @@ module Tabry
16
16
  end
17
17
  end
18
18
 
19
- def options(token, used:)
19
+ def options(token, used:, params:)
20
20
  to_a.map do |flag|
21
21
  if token&.start_with?("-") && flag.name_with_dashes.start_with?(token) && !used[flag.name]
22
- flag.name_with_dashes
22
+ if params[:descriptions]
23
+ [flag.name_with_dashes, flag.description]
24
+ else
25
+ flag.name_with_dashes
26
+ end
23
27
  end
24
28
  end.compact
25
29
  end
@@ -7,8 +7,8 @@ module Tabry
7
7
  class IncludeOption < OptionBase
8
8
  attr_reader :include_name, :_root
9
9
 
10
- def options(token)
11
- flatten.options(token)
10
+ def options(token, params)
11
+ flatten.options(token, params)
12
12
  end
13
13
 
14
14
  def flatten
@@ -6,7 +6,7 @@ module Tabry
6
6
  module Models
7
7
  class MethodOption < OptionBase
8
8
  # TODO: Handled upstream for now, could change later.
9
- def options(_token)
9
+ def options(_token, _params)
10
10
  [value.to_sym]
11
11
  end
12
12
  end
@@ -10,8 +10,8 @@ module Tabry
10
10
  super(**args, klass: Option)
11
11
  end
12
12
 
13
- def options(token)
14
- to_a.map { |option| option.options(token) }.inject(&:|)
13
+ def options(token, params)
14
+ to_a.map { |option| option.options(token, params) }.inject(&:|)
15
15
  end
16
16
  end
17
17
  end
@@ -5,7 +5,7 @@ require_relative "option_base"
5
5
  module Tabry
6
6
  module Models
7
7
  class ShellOption < OptionBase
8
- def options(token)
8
+ def options(token, _params)
9
9
  `#{value}`.chomp.split("\n").select { |opt| opt.start_with?(token) }
10
10
  end
11
11
  end
@@ -20,9 +20,20 @@ module Tabry
20
20
  end
21
21
  end
22
22
 
23
- def options(token)
24
- to_a.map(&:name).select { |name| name.start_with?(token) }
23
+ def options(token, params)
24
+ ::Tabry::Util.debug "checking:::: #{token}"
25
+ to_a
26
+ .select { |sub| sub.name.start_with?(token) }
27
+ .map do |sub|
28
+ if params[:descriptions]
29
+ [sub.name, sub.description]
30
+ else
31
+ sub.name
32
+ end
33
+ end
34
+ .compact
25
35
  end
36
+
26
37
  end
27
38
  end
28
39
  end
@@ -4,15 +4,16 @@ require "json"
4
4
 
5
5
  module Tabry
6
6
  class OptionsFinder
7
- attr_reader :result
7
+ attr_reader :result, :params
8
8
 
9
9
  # Returns an array of options
10
- def self.options(result, token)
11
- new(result).options(token)
10
+ def self.options(result, token, params)
11
+ new(result, params).options(token)
12
12
  end
13
13
 
14
- def initialize(result)
14
+ def initialize(result, params)
15
15
  @result = result
16
+ @params = params
16
17
  end
17
18
 
18
19
  def options(token)
@@ -59,7 +60,7 @@ module Tabry
59
60
 
60
61
  def options_flagarg(token)
61
62
  result.sub_stack.map do |sub|
62
- sub.flags[state.current_flag]&.options&.options(token)
63
+ sub.flags[state.current_flag]&.options&.options(token, params)
63
64
  end.compact.flatten.uniq
64
65
  end
65
66
 
@@ -68,14 +69,18 @@ module Tabry
68
69
  # once an arg has been given, can no longer use a subcommand
69
70
  []
70
71
  else
71
- current_sub.subs.options(token)
72
+ current_sub.subs.options(token, params)
72
73
  end
73
74
  end
74
75
 
75
76
  def options_subcommand_flags(token)
76
77
  return [] if state.dashdash
77
78
 
78
- result.sub_stack.map { |sub| sub.flags.options(token, used: state.flags) }.flatten.uniq
79
+ result
80
+ .sub_stack
81
+ .map { |sub| sub.flags.options(token, used: state.flags, params: params) }
82
+ .flatten(1)
83
+ .uniq
79
84
  end
80
85
 
81
86
  def options_subcommand_args(token)
@@ -85,7 +90,7 @@ module Tabry
85
90
  current_sub.args[state.args.length]
86
91
  end
87
92
 
88
- arg&.options&.options(token) || []
93
+ arg&.options&.options(token, params) || []
89
94
  end
90
95
  end
91
96
  end
data/lib/tabry/runner.rb CHANGED
@@ -19,8 +19,8 @@ module Tabry
19
19
  end
20
20
  end
21
21
 
22
- def options(args, last = nil)
23
- Tabry::OptionsFinder.options(parse(args), last)
22
+ def options(args, last = nil, params = {})
23
+ Tabry::OptionsFinder.options(parse(args), last, params)
24
24
  end
25
25
 
26
26
  def parse(args)
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "shellwords"
4
+ require "yaml"
5
+ require_relative "../../util"
6
+ require_relative "../../runner"
7
+ require_relative "../../shell_tokenizer"
8
+
9
+ # Fish-specific entrypoint
10
+ module Tabry
11
+ module Fish
12
+ module Wrapper
13
+ DESCRIPTION_MAX_LENGTH = 50
14
+
15
+ def self.run(cmd_line, comp_point, config: nil)
16
+ cmd_name, args, last_arg = Tabry::ShellTokenizer.split_with_comppoint(cmd_line, comp_point)
17
+ opts = Tabry::Runner.new(config: config || cmd_name).options(args, last_arg, {descriptions: true})
18
+
19
+ if Tabry::Util.debug?
20
+ $stderr.puts
21
+ warn "debug: got command line and comp_point: #{cmd_line.inspect}, #{comp_point}"
22
+ warn "using args: #{args.inspect}"
23
+ warn "using lastarg: #{last_arg.inspect}"
24
+ warn "results from Tabry#options(): #{opts.inspect}"
25
+ warn "--- end debug output ---"
26
+ end
27
+
28
+ normal_opts = opts.select { |t,| t.is_a?(String) }
29
+ special_opts = opts.select { |t| t.is_a?(Symbol) }
30
+
31
+ puts normal_opts.map { |opt, desc| "#{Shellwords.escape(opt)}\t#{format_description(desc)}" }.join("\n")
32
+ if special_opts.any?
33
+ puts
34
+ puts special_opts.join("\n")
35
+ end
36
+ end
37
+
38
+ def self.format_description(description)
39
+ if description.nil?
40
+ ""
41
+ else
42
+ if description.length > DESCRIPTION_MAX_LENGTH
43
+ "#{description[0..(DESCRIPTION_MAX_LENGTH - 3)]}..."
44
+ else
45
+ description
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Used to generate a tab-completion function for a Tabry CLI using absolute
4
+ # paths to the tabry-bash script in this repo and to the Tabry JSON/YML file.
5
+ # Using uniquely-named tab-completion functions and absolute paths means you can
6
+ # have different Tabry-based CLIs using different versions of Tabry without any
7
+ # conflicts.
8
+ # See sh/bash/README.md and "Adding Tab Completion to your CLI" in main README
9
+
10
+ require "shellwords"
11
+
12
+ module Tabry
13
+ module Shells
14
+ module Fish
15
+ # NOTE! This code uses sh/fish/tabry_fish.fish and is described in
16
+ # sh/fish/README.md; see that README for more info
17
+ def self.generate(cmd_name, tabry_file_path, uniq_fn_id: nil)
18
+ generate_internal(
19
+ cmd_name: cmd_name,
20
+ import_path: File.expand_path(tabry_file_path),
21
+ tabry_fish_executable: File.expand_path("#{path_to_tabry}/bin/tabry-fish"),
22
+ tabry_fish_arg: nil,
23
+ uniq_fn_id: uniq_fn_id
24
+ )
25
+ end
26
+
27
+ # Generate fish completion code that will run the currently running
28
+ # command ($0) with "completion" to get completion options. "cmd_name"
29
+ # is used to tell fish which command to make options for
30
+ def self.generate_self(cmd_name: nil)
31
+ cmd_name ||= File.basename($0)
32
+ generate_internal(
33
+ cmd_name: cmd_name,
34
+ import_path: "",
35
+ tabry_fish_executable: File.expand_path($0),
36
+ tabry_fish_arg: "completion",
37
+ )
38
+ end
39
+
40
+ def self.path_to_tabry
41
+ File.expand_path("#{__dir__}/../../../")
42
+ end
43
+
44
+ def self.esc(s)
45
+ Shellwords.escape(s)
46
+ end
47
+
48
+ def self.add_uniq_id(str, pattern, uniq_id)
49
+ str.gsub! pattern, "#{pattern}_#{uniq_id}"
50
+ end
51
+
52
+ def self.generate_internal(cmd_name:, import_path:, tabry_fish_executable:, tabry_fish_arg:, uniq_fn_id: nil)
53
+ # uniq_fn_id is added to the bash functions to ensure they are unique
54
+ # -- by default this is the capitalized command name
55
+ uniq_fn_id ||= cmd_name
56
+ uniq_fn_id = uniq_fn_id.upcase.gsub(/[^A-Z0-9_]/, "_")
57
+ script = File.read("#{__dir__}/../../../sh/fish/tabry_fish.fish")
58
+
59
+ add_uniq_id(script, "tabry_completion_init", uniq_fn_id)
60
+ add_uniq_id(script, "__fish_tabry_internal_invoke", uniq_fn_id)
61
+ add_uniq_id(script, "__fish_tabry_check_only_args", uniq_fn_id)
62
+ add_uniq_id(script, "__fish_tabry_check_only_file", uniq_fn_id)
63
+ add_uniq_id(script, "__fish_tabry_check_args_and_file", uniq_fn_id)
64
+ add_uniq_id(script, "__fish_tabry_completions", uniq_fn_id)
65
+
66
+ script.gsub! "# TABRY_IMPORT_PATH_REPLACE (DO NOT REMOVE)", "set TABRY_IMPORTS_PATH #{esc import_path}"
67
+ script.gsub! "# TABRY_EXECUTABLE_REPLACE (DO NOT REMOVE)", "set TABRY_EXECUTABLE #{esc tabry_fish_executable}"
68
+ if !tabry_fish_arg.nil?
69
+ script.gsub! "# TABRY_ARG_REPLACE (DO NOT REMOVE)", "set TABRY_ARG #{esc tabry_fish_arg}"
70
+ end
71
+
72
+ <<~END_FISH_CODE_TEMPLATE
73
+ # The following Autocomplete is for a Tabry-powered command. It was
74
+ # generated by the command itself. See the documentation located in
75
+ # #{esc path_to_tabry}/sh/fish/README.md
76
+ #{script}
77
+ tabry_completion_init_#{uniq_fn_id} #{esc cmd_name}
78
+ END_FISH_CODE_TEMPLATE
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,3 @@
1
+ module Tabry
2
+ VERSION = "0.2.4"
3
+ end
data/sh/fish/README.md CHANGED
@@ -2,8 +2,9 @@ This directory includes fish completions for Tabry
2
2
 
3
3
  There are two steps to add to your ~/.config/fish/config.fish to use:
4
4
 
5
- 1. Source this file
5
+ 1. Source `tabry_fish.fish`
6
6
  2. Add a call to `tabry_completion_init`, for each command
7
+ 3. Ensure the `TABRY_IMPORTS_PATH` environment variable is defined and points to where your compiled tabry files are located.
7
8
 
8
9
  ```sh
9
10
  source tabry_fish.fish
@@ -12,14 +12,19 @@ end
12
12
 
13
13
  # return true if tabry only reports commands
14
14
  function __fish_tabry_internal_invoke
15
- set SCRIPT (status --current-filename)
16
- set SCRIPT_DIR (dirname $SCRIPT)
15
+ # TABRY_IMPORT_PATH_REPLACE (DO NOT REMOVE)
16
+ # TABRY_EXECUTABLE_REPLACE (DO NOT REMOVE)
17
+ # TABRY_ARG_REPLACE (DO NOT REMOVE)
18
+ set -x TABRY_FISH_MODE true
17
19
 
18
20
  # -C "Get cursor position"
19
21
  set cursor_position (commandline -C)
20
22
  set cmd (commandline)
21
- set result ($SCRIPT_DIR/../../bin/tabry-bash "$cmd" "$cursor_position")
22
- echo $result
23
+
24
+ set result ($TABRY_EXECUTABLE $TABRY_ARG "$cmd" "$cursor_position")
25
+ for arg in $result
26
+ echo $arg
27
+ end
23
28
  end
24
29
 
25
30
  # return true if tabry only reports file
@@ -75,16 +80,14 @@ function __fish_tabry_completions
75
80
 
76
81
  set args (echo "$result"|sed 's/ .*//')
77
82
 
78
- # The '--' arg is needed in case $result contains flag-like strings
79
- set args_parsed (string split -- ' ' $args)
80
-
81
83
  if test "x$args" = "x"
82
84
  # Don't offer anything if we don't have any completions
83
85
  return 1;
84
86
  else
85
- # $args_parsed will be something like: ["foo" "bar" "baz" "" "file"]
87
+ # $result will be something like: ["foo 'this is foo'" "bar" "baz" "" "file"]
86
88
  # where "file" is special, since it's after the space.
87
- for arg in $args_parsed
89
+ for arg in $result
90
+ set clean_arg (echo "$arg"|sed 's/ .*//')
88
91
  if test "x$arg" != "x"
89
92
  echo "$arg"
90
93
  else
@@ -3,6 +3,7 @@
3
3
  require_relative "../../../lib/tabry/cli/all_in_one"
4
4
  require_relative "../../../lib/tabry/shells/bash"
5
5
  require_relative "../../../lib/tabry/shells/bash/wrapper"
6
+ require_relative "../../../lib/tabry/shells/fish"
6
7
 
7
8
  module Tabry::Spec
8
9
  module Cli
@@ -124,6 +125,17 @@ describe Tabry::CLI::AllInOne do
124
125
  end
125
126
  end
126
127
 
128
+ it "creates a #completion__fish method which generates completion" do
129
+ stub_const("ARGV", %w[completion fish])
130
+ expect(Tabry::Shells::Fish).to receive(:generate_self).with(cmd_name: "foo").and_return("fish completion stuff")
131
+ expect_any_instance_of(Kernel).to receive(:puts).with("fish completion stuff")
132
+
133
+ described_class.completion_only do
134
+ cmd :foo
135
+ sub :bar
136
+ end
137
+ end
138
+
127
139
  it "creates a #completion method which generates options" do
128
140
  stub_const("ARGV", ["completion", "cmd line", "6"])
129
141
  expect(Tabry::Bash::Wrapper).to receive(:run) do |cmd_line, comp_point, config:|
data/tabry.gemspec CHANGED
@@ -1,12 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # TODO: these 2 lines are cargo cult
4
- lib = File.expand_path("lib", __dir__)
5
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require_relative './lib/tabry/version'
6
4
 
7
5
  Gem::Specification.new do |s|
8
6
  s.name = "tabry"
9
- s.version = "0.2.3"
7
+ s.version = Tabry::VERSION
10
8
  s.summary = "Tab completion and CLIs extraordinaire"
11
9
  s.authors = ["Evan Battaglia"]
12
10
  s.email = "battaglia.evan@gmail.com"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tabry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Battaglia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-23 00:00:00.000000000 Z
11
+ date: 2023-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry-byebug
@@ -84,7 +84,9 @@ description:
84
84
  email: battaglia.evan@gmail.com
85
85
  executables:
86
86
  - tabry-bash
87
+ - tabry-fish
87
88
  - tabry-generate-bash-complete
89
+ - tabry-generate-fish-complete
88
90
  - tabry-help
89
91
  - tabry-test-options
90
92
  - tabry-test-parse
@@ -92,7 +94,9 @@ extensions: []
92
94
  extra_rdoc_files: []
93
95
  files:
94
96
  - bin/tabry-bash
97
+ - bin/tabry-fish
95
98
  - bin/tabry-generate-bash-complete
99
+ - bin/tabry-generate-fish-complete
96
100
  - bin/tabry-help
97
101
  - bin/tabry-test-options
98
102
  - bin/tabry-test-parse
@@ -148,9 +152,12 @@ files:
148
152
  - lib/tabry/shell_tokenizer.rb
149
153
  - lib/tabry/shells/bash.rb
150
154
  - lib/tabry/shells/bash/wrapper.rb
155
+ - lib/tabry/shells/fish.rb
156
+ - lib/tabry/shells/fish/wrapper.rb
151
157
  - lib/tabry/state.rb
152
158
  - lib/tabry/usage_generator.rb
153
159
  - lib/tabry/util.rb
160
+ - lib/tabry/version.rb
154
161
  - sh/bash/README.md
155
162
  - sh/bash/tabry_bash.sh
156
163
  - sh/bash/tabry_bash_core.sh