dry-cli-completion 0.3.0 → 0.9.0.pre.alpha

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: eb611ff121ae25f5f4b8cbe926d7742a28885e2408cabb2e589fce724d67b85c
4
- data.tar.gz: '008ba658f43ec5177037e31f0bf4e78aafbfcbb866065e1cbd702117815495f3'
3
+ metadata.gz: f964195592d079499e1ac64d97966be5041cec718b12d7dbdcad3a13a78a987c
4
+ data.tar.gz: 19eb60e90e5d136ac43762f8c897b7f3b9d0197074e12c3a7237ad96230034e2
5
5
  SHA512:
6
- metadata.gz: 9362523877d4147af5ffdbbb53a54158ffee4b2a5709c6e3aa854197da105f391861fd6daacd80bedf0d1b7b4fbb1cd520e9a5abb56cdc4dd83b384ba0d8504a
7
- data.tar.gz: b5603912acb40ff3a2d4e0cdf2c8734a86cef9572139b9087e31d33e84d833bd081c47f7429716aa18a8a6ed0804780004234090eb82a68f4b28cbbad39ab976
6
+ metadata.gz: 85b055c56a7fd6c9752449275766126f57a51aa2a74e976246b62b25b4a7625cc858b794121d5443b03020cee8407cc00b4fdb79be1c3cbb8b7d738255d10dbf
7
+ data.tar.gz: 943acef312431e8176115bea9c3dcdbcef4960640eb409f391a731442b1098f7dbafb5562546c120e00f01524c4087d54b98cd505688923d5de3bcc3a18ff109
data/CHANGELOG.md CHANGED
@@ -1,3 +1,5 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.9.0-alpha First full fledged Implementation
4
+
3
5
  ## 0.3.0 Inital Skeleton
data/Gemfile CHANGED
@@ -7,3 +7,5 @@ gemspec
7
7
 
8
8
  gem "rspec", "~> 3.0"
9
9
  gem "standard"
10
+ gem "dry-cli"
11
+ gem "pry"
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2022 Tobias Bielohlawek
3
+ Copyright (c) 2022 Tobias Bielohlawek (rngtng)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,15 +1,15 @@
1
- # Dry::Cli::Completion
2
-
3
- Dry::CLI Command to generate a completion script for bash/zsh
1
+ # Dry::CLI::Completion
4
2
 
5
3
  [![Gem Version](https://badge.fury.io/rb/dry-cli-completion.svg)](https://badge.fury.io/rb/dry-cli-completion)
6
4
 
7
- ## About
5
+ ---
8
6
 
9
- Extension Command for Dry::CLI which generates a completion script for bash/zsh.
7
+ [Dry::CLI](https://github.com/dry-rb/dry-cli) extension & drop-in Command to generate a completion
8
+ script for bash/zsh. It heavily relies on the great work of https://github.com/dannyben/completely.
10
9
 
11
- ## Installation
10
+ ---
12
11
 
12
+ ## Installation
13
13
  Add this line to your application's Gemfile:
14
14
 
15
15
  ```ruby
@@ -25,18 +25,112 @@ Or install it yourself as:
25
25
  $ gem install dry-cli-completion
26
26
 
27
27
  ## Usage
28
+ The gems architecture consits of three layers which each abstracts & simplifies the completion script generation and its usage:
28
29
 
29
- TODO: Write usage instructions here
30
+ 1. Command layer - drop-in dry-cli command to print the completion script for given shell
31
+ 2. Generator layer - the actual script generation leveraging [completely](https://github.com/dannyben/completely)
32
+ 3. Input layer - interspecting the dry-cli registry to extract each command with it options, arguements and aliases
30
33
 
31
- ## Development
34
+ ### 1. Command layer
35
+ Simplest usage is to drop in the `Dry::CLI::Completion::Command` to your existing registry:
36
+
37
+ ```ruby
38
+ module MyRegistry
39
+ extend Dry::CLI::Registry
40
+
41
+ register "cmd1", MyCmd1
42
+ #....
43
+
44
+ register "completion", Dry::CLI::Completion::Command[self]
45
+ end
46
+ end
47
+ ```
32
48
 
49
+ This will extend your cli for a new command `completion` with following usage:
50
+
51
+ ```sh
52
+ Usage:
53
+ foo-cli completion [SHELL]
54
+
55
+ Description:
56
+ Print tab completion script for given shell
57
+
58
+ Arguments:
59
+ SHELL # Shell for which to print the completion script: (bash/zsh)
60
+
61
+ Options:
62
+ --[no-]include-aliases, -a # Include command aliases when true, default: false
63
+ --help, -h # Print this help
64
+
65
+ Examples:
66
+ foo-cli completion bash # Print tab completion script for bash
67
+ foo-cli completion zsh # Print tab completion script for zsh
68
+ foo-cli completion -a bash # Include command aliases for bash
69
+ ```
70
+
71
+ ### 2. Generator Layer
72
+ In case you want to change/extend the completion script, create a custom command and leverage just the generator:
73
+
74
+ ```ruby
75
+ class MyCommand < Dry::CLI::Command
76
+ desc "Custom completion script command"
77
+
78
+ def call(**)
79
+ script = Dry::CLI::Completion::Generator.new(MyRegistry).call(shell: "bash")
80
+ # ... further processing here ...
81
+ puts script
82
+ end
83
+ end
84
+ ```
33
85
 
34
- For local development, this project comes with a Dockerimage and Makefile. After checking out the repo, run the following to enter development console:
86
+ ### 3. Input layer
87
+ Lastly, if the script generation input needs to be adjusted, leverage the input layer. Here the commands, arguments, options and their values/types extracted and put in an input format for `completely`. See [completely Readme](https://github.com/dannyben/completely) for details.
35
88
 
89
+ ```ruby
90
+ input = Dry::CLI::Completion::Input.new(MyRegistry, "foo").call(include_aliases: false)
91
+ # ... further processing here ...
92
+ puts Completely::Completions.new(input)
36
93
  ```
37
- make build dev
94
+
95
+ ## Development
96
+ For local development, this project comes dockerized - with a Dockerimage and Makefile. After checking out the repo, run the following to enter development console:
97
+
98
+ $ make build dev
99
+
100
+ With that, any dependencies are maintained and no ruby version manager is required.
101
+
102
+ ### Testing
103
+ The gem comes with a full-fledged rspec testsuite. To execute all tests run in developer console:
104
+
105
+ $ rspec
106
+
107
+ ### Manual Testing
108
+ The foo registry is used in unit test is available as `spec/foo-cli` for manual testing. First source the comepltion script:
109
+
110
+ $ source <(spec/foo-cli completion bash)
111
+
112
+ Then try the tab completion yourself:
113
+
114
+ ```sh
115
+ $ spec/foo-cli <tab>
116
+ completion echo exec help start stop version
38
117
  ```
39
118
 
40
- Then, run `rake spec` to run the tests.
119
+ ### Linting
120
+ For liniting, the gem leverages the [standard Readme](https://github.com/testdouble/standard) and [rubocop](https://github.com/rubocop/rubocop) rules. To execute just run:
121
+
122
+ $ rubocop
123
+
124
+ ### Releasing
125
+ To release a new version, update the version number in `version.rb`, push commits to GitHub and then create a release. This will create a git tag for the version, and push the `.gem` file to [rubygems.org](https://rubygems.org) as well as GitHub packages.
126
+ See GitHub actions in `.github` for more.
127
+
128
+ ## Supported Ruby versions
129
+
130
+ This library officially supports the following Ruby versions:
131
+
132
+ * MRI `>= 2.7.0`
133
+
134
+ ## License
41
135
 
42
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
136
+ See `LICENSE` file.
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/dry/cli/completion/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "dry-cli-completion"
7
+ spec.version = Dry::CLI::Completion::VERSION
8
+ spec.authors = ["rngtng"]
9
+ spec.email = ["tobi@rngtng.com"]
10
+ spec.licenses = ["MIT"]
11
+
12
+ spec.summary = "Dry::CLI Command to generate a completion script for bash/zsh"
13
+ spec.description = "Extension Command for Dry::CLI which generates a completion script for bash/zsh."
14
+ spec.homepage = "https://github.com/rngtng/dry-cli-completion"
15
+ spec.metadata = {
16
+ "homepage_uri" => spec.homepage,
17
+ "source_code_uri" => "https://github.com/rngtng/dry-cli-completion",
18
+ "changelog_uri" => "https://github.com/rngtng/dry-cli-completion/CHANGELOG.md",
19
+ "github_repo" => "ssh://github.com/rngtng/dry-cli-completion",
20
+ "rubygems_mfa_required" => "true"
21
+ }
22
+
23
+ spec.files = Dir["lib/**/*"] + %w[Gemfile LICENSE README.md CHANGELOG.md dry-cli-completion.gemspec]
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.required_ruby_version = ">= 2.7.6"
27
+
28
+ spec.add_dependency "completely", "~> 0.4"
29
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/cli/completion"
4
+
5
+ module Dry
6
+ class CLI
7
+ module Completion
8
+ class Command < Dry::CLI::Command
9
+ desc "Print tab completion script for given shell"
10
+
11
+ example [
12
+ "bash # Print tab completion script for bash",
13
+ "zsh # Print tab completion script for zsh",
14
+ "-a bash # Include command aliases for bash"
15
+ ]
16
+
17
+ option :include_aliases, required: true, type: :boolean, default: false, aliases: ["a"],
18
+ desc: "Include command aliases when true"
19
+ argument :shell, required: false, type: :string, values: Dry::CLI::Completion::SUPPORTED_SHELLS,
20
+ desc: "Shell for which to print the completion script"
21
+
22
+ def call(shell:, include_aliases: false, **)
23
+ puts Generator.new(self.class.registry).call(
24
+ shell: shell,
25
+ include_aliases: include_aliases
26
+ )
27
+ end
28
+
29
+ def self.[](registry)
30
+ @registry = registry
31
+ self
32
+ end
33
+
34
+ class << self
35
+ attr_reader :registry
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "input"
4
+ require "completely"
5
+
6
+ module Dry
7
+ class CLI
8
+ module Completion
9
+ class Generator
10
+ def initialize(registry, program_name: nil)
11
+ @registry = registry
12
+ @program_name = program_name || Dry::CLI::ProgramName.call
13
+ end
14
+
15
+ def call(shell:, include_aliases: false, out: StringIO.new)
16
+ raise ArgumentError, "Unknown shell" unless SUPPORTED_SHELLS.include?(shell)
17
+ if shell == ZSH
18
+ out.puts "# enable bash completion support, see https://github.com/dannyben/completely#completions-in-zsh"
19
+ out.puts "autoload -Uz +X compinit && compinit"
20
+ out.puts "autoload -Uz +X bashcompinit && bashcompinit"
21
+ end
22
+
23
+ out.puts Completely::Completions.new(
24
+ Input.new(@registry, @program_name).call(include_aliases: include_aliases)
25
+ ).script
26
+ out.string
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ class CLI
5
+ module Completion
6
+ class Input
7
+ def initialize(registry, program_name)
8
+ @registry = registry
9
+ @program_name = program_name
10
+ end
11
+
12
+ def call(include_aliases:)
13
+ nodes = root_node.children.dup
14
+ nodes.merge!(root_node.aliases.dup) if include_aliases
15
+
16
+ commands = nodes.each_with_object({}) do |(name, sub_node), hash|
17
+ next unless sub_node.command
18
+ hash[name] = command(sub_node.command, include_aliases: include_aliases)
19
+ end
20
+
21
+ commands.each_with_object({
22
+ @program_name => commands.keys + ["help"]
23
+ }) do |(name, config), input|
24
+ input_line(input, "#{@program_name} #{name}", config[:arguments].shift, config)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def root_node
31
+ @registry.get({}).instance_variable_get(:@node)
32
+ end
33
+
34
+ def command(command, include_aliases: false)
35
+ {
36
+ options: {
37
+ "--help" => []
38
+ },
39
+ arguments: command.arguments.map { |arg|
40
+ [arg.name, argument_values(arg)]
41
+ }
42
+ }.tap do |hash|
43
+ command.options.each do |opt|
44
+ hash[:options]["--#{opt.name}"] = option_values(opt)
45
+ next unless include_aliases
46
+ opt.aliases.each { |arg|
47
+ hash[:options]["-#{arg}"] = option_values(opt)
48
+ }
49
+ end
50
+ end
51
+ end
52
+
53
+ def argument_values(argument)
54
+ return ["<file>"] if argument.name.to_s.include?("path")
55
+ return argument.values if argument.values
56
+ nil
57
+ end
58
+
59
+ def option_values(option)
60
+ return ["<file>"] if option.name.to_s.include?("path")
61
+ return option.values if option.values
62
+ return [] if option.type != :boolean
63
+ nil
64
+ end
65
+
66
+ def input_line(input, name, argument, config)
67
+ return if name.include?("<file>")
68
+ if argument
69
+ arg_values = argument.last || []
70
+ input[name] = arg_values + config[:options].keys
71
+ argument = config[:arguments].shift
72
+ arg_values.each { |v| input_line(input, "#{name}*#{v}", argument, config) }
73
+ else
74
+ input[name] = config[:options].keys
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dry
4
- module Cli
4
+ class CLI
5
5
  module Completion
6
- VERSION = "0.3.0"
6
+ VERSION = "0.9.0-alpha"
7
7
  end
8
8
  end
9
9
  end
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "completion/version"
4
+ require_relative "completion/generator"
4
5
 
5
6
  module Dry
6
- module Cli
7
+ class CLI
7
8
  module Completion
8
- class Error < StandardError; end
9
- # Your code goes here...
9
+ SUPPORTED_SHELLS = [
10
+ BASH = "bash",
11
+ ZSH = "zsh"
12
+ ]
10
13
  end
11
14
  end
12
15
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-cli-completion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.9.0.pre.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - rngtng
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-24 00:00:00.000000000 Z
11
+ date: 2022-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: completely
@@ -32,18 +32,16 @@ executables: []
32
32
  extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
- - ".rspec"
36
- - ".rubocop.yml"
37
35
  - CHANGELOG.md
38
- - Dockerfile
39
36
  - Gemfile
40
37
  - LICENSE
41
- - Makefile
42
38
  - README.md
43
- - Rakefile
39
+ - dry-cli-completion.gemspec
44
40
  - lib/dry/cli/completion.rb
41
+ - lib/dry/cli/completion/command.rb
42
+ - lib/dry/cli/completion/generator.rb
43
+ - lib/dry/cli/completion/input.rb
45
44
  - lib/dry/cli/completion/version.rb
46
- - sig/dry/cli/completion.rbs
47
45
  homepage: https://github.com/rngtng/dry-cli-completion
48
46
  licenses:
49
47
  - MIT
@@ -51,6 +49,8 @@ metadata:
51
49
  homepage_uri: https://github.com/rngtng/dry-cli-completion
52
50
  source_code_uri: https://github.com/rngtng/dry-cli-completion
53
51
  changelog_uri: https://github.com/rngtng/dry-cli-completion/CHANGELOG.md
52
+ github_repo: ssh://github.com/rngtng/dry-cli-completion
53
+ rubygems_mfa_required: 'true'
54
54
  post_install_message:
55
55
  rdoc_options: []
56
56
  require_paths:
@@ -62,9 +62,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
62
62
  version: 2.7.6
63
63
  required_rubygems_version: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - ">="
65
+ - - ">"
66
66
  - !ruby/object:Gem::Version
67
- version: '0'
67
+ version: 1.3.1
68
68
  requirements: []
69
69
  rubygems_version: 3.3.7
70
70
  signing_key:
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
data/.rubocop.yml DELETED
@@ -1,9 +0,0 @@
1
- require: standard
2
-
3
- inherit_gem:
4
- standard: config/base.yml
5
-
6
- AllCops:
7
- TargetRubyVersion: 2.7
8
- Exclude:
9
- - 'vendor/**/*'
data/Dockerfile DELETED
@@ -1,19 +0,0 @@
1
- FROM ruby:2.7-slim
2
-
3
- RUN set -ex \
4
- && apt update \
5
- && apt install -y --no-install-recommends build-essential git
6
-
7
- RUN mkdir /app
8
-
9
- # COPY Gemfile Gemfile.lock /app/
10
-
11
- WORKDIR /app
12
- # RUN bundle install
13
- # RUN bundle binstubs --all --path /bin
14
-
15
- COPY . /app
16
-
17
- ENV HISTCONTROL=ignoreboth:erasedups
18
-
19
- ENTRYPOINT ["bash"]
data/Makefile DELETED
@@ -1,20 +0,0 @@
1
- PROJECT ?= rngtng/dry-cli-completion
2
- BUILD_TAG ?= dev
3
- REGISTRY_TAG = $(PROJECT):$(BUILD_TAG)
4
-
5
- .PHONY: help # List all documented targets
6
- help:
7
- @grep '^.PHONY: .* #' Makefile | sed 's/\.PHONY: \(.*\) # \(.*\)/\1 $(shell echo "\t") \2/' | sort | expand -t20
8
-
9
- .PHONY: build # Build docker image with `dev` tag
10
- build:
11
- docker build -t $(REGISTRY_TAG) .
12
-
13
- .PHONY: test-gh-action # Test github actions locally with https://github.com/nektos/act
14
- test-gh-action:
15
- echo '{ "inputs": { "tag": "0.1.0" } }' > /tmp/act.json
16
- act --artifact-server-path /tmp/artifacts workflow_dispatch -e /tmp/act.json
17
-
18
- .PHONY: dev # Build docker image, run and ssh inside
19
- dev:
20
- docker run --rm -it -v "$(shell pwd):/app" $(REGISTRY_TAG)
data/Rakefile DELETED
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
5
-
6
- RSpec::Core::RakeTask.new(:spec)
7
-
8
- require "rubocop/rake_task"
9
-
10
- RuboCop::RakeTask.new
11
-
12
- task default: %i[spec rubocop]
@@ -1,8 +0,0 @@
1
- module Dry
2
- module Cli
3
- module Completion
4
- VERSION: String
5
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
6
- end
7
- end
8
- end