fylla 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 99136984f7eb5a2b198e68ee41681aff9bfa3c97
4
+ data.tar.gz: 2396f92bc99adcba4049207a0c6f19977c76fa4a
5
+ SHA512:
6
+ metadata.gz: 3cc21ab97adc324024605fbab5ffb62c3cae1b4e4d90eb2308cbed9d4a025e1c3b31fc943e88b07e133cea46697477acc13936ab67da26110295a3faf490d4b1
7
+ data.tar.gz: 654490096828d6a4416533dd07088e783a4e1c9703104b48db939f84598d35d9ecd88d4c86047e8d7ca074125260c914244cbb23472c5e439562e5e7ced3f9da
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in Fylla.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Tyler Thrailkill
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task default: :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'fylla'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/exe/fylla ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fylla'
data/fylla.gemspec ADDED
@@ -0,0 +1,41 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'fylla/version'
4
+
5
+ # rubocop:disable BlockLength
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'fylla'
8
+ spec.version = Fylla::VERSION
9
+ spec.authors = ['Tyler Thrailkill']
10
+ spec.email = ['tyler.b.thrailkill@gmail.com']
11
+
12
+ spec.summary = 'Adds functions for generating autocomplete scripts for Thor applications'
13
+ spec.description = '
14
+ Fylla generates zsh and bash autocomplete scripts for Thor CLI applications.
15
+ '
16
+ spec.homepage = 'https://github.com/snowe2010/fylla'
17
+ spec.license = 'MIT'
18
+
19
+ spec.metadata['yard.run'] = 'yri' # use "yard" to build full HTML docs.
20
+ # spec.metadata['changelog_uri'] = "TODO: Put your gem's CHANGELOG.md URL here."
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(.idea|test|spec|features)/|^[.][a-zA-Z0-9]|^.*[.]md|Gemfile.lock})
27
+ end
28
+ end
29
+
30
+ spec.bindir = 'exe'
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ['lib']
33
+
34
+ spec.add_development_dependency 'bundler', '~> 2.0'
35
+ spec.add_development_dependency 'minitest', '~> 5.0'
36
+ spec.add_development_dependency 'minitest-hooks', '~> 1.5.0'
37
+ spec.add_development_dependency 'rake', '~> 10.0'
38
+ # spec.add_development_dependency 'thor', '~> 0.20.3'
39
+ spec.add_dependency 'thor', '>= 0.19.0'
40
+ end
41
+ # rubocop:enable BlockLength
@@ -0,0 +1,158 @@
1
+ require_relative 'parsed_command'
2
+ require_relative 'parsed_subcommand'
3
+ require 'erb'
4
+
5
+ module Fylla
6
+ module Thor
7
+ #
8
+ # module for prepending into +Thor+
9
+ # inserts methods into Thor that allow generating completion scripts
10
+ module CompletionGenerator
11
+ def self.prepended(base)
12
+ base.singleton_class.prepend(ClassMethods)
13
+ end
14
+
15
+ #
16
+ # Contains the methods +zsh_completion+
17
+ module ClassMethods
18
+ #
19
+ # Generates a zsh _[executable_name] completion
20
+ # script for the entire Thor application
21
+ #
22
+ # @param executable_name [String]
23
+ # the name of the executable to generate the script for
24
+ def zsh_completion(executable_name)
25
+ command = create_command_map commands, subcommand_classes
26
+
27
+ help = create_completion_string(read_template(:zsh, :help), binding)
28
+ builder = map_to_completion_string [command], executable_name
29
+ completion = "#compdef _#{executable_name} #{executable_name}\n"
30
+ completion += builder
31
+ completion += help
32
+ completion
33
+ end
34
+
35
+ private
36
+
37
+ # Takes a list of [ParsedCommand]s and [ParsedSubcommand]s
38
+ # and converts them into completion strings, to be combined
39
+ # together into one completion script
40
+ #
41
+ # @param style [Symbol] style of completions to generate
42
+ # defaults to :zsh
43
+ # @param commands [List<Thor::Command>]
44
+ # list of [Thor::Command]s
45
+ # @param context [String] the current command context
46
+ # this is essentially a breadcrumb of our current
47
+ # command path:
48
+ # e.g. "exe sub1 sub2 sub3 --help" maps to a context of
49
+ # "_sub1_sub2_sub3"
50
+ # @param class_options [List<Thor::Option>]
51
+ # a list of global or class level options for the current context
52
+ # @param executable_name [String] the executable name, for use in
53
+ # method calls and to name the completion script.
54
+ def map_to_completion_string(commands,
55
+ context = '',
56
+ class_options = [],
57
+ executable_name = '',
58
+ style = :zsh)
59
+ builder = ''
60
+ commands.each do |command|
61
+ context_name = generate_context_name(context, command)
62
+ result = generate_completion_string(command, class_options, context_name, executable_name, style)
63
+ builder += result
64
+ end
65
+ builder
66
+ end
67
+
68
+ # Generate a context name based off of
69
+ # the current context and the current command
70
+ #
71
+ # @param context [String] the current context
72
+ # @param command [Thor::Command]
73
+ # current command we are generating documentation for
74
+ def generate_context_name(context, command)
75
+ command_name = if command.name.nil? || command.name.empty?
76
+ ''
77
+ else
78
+ "_#{command.name}"
79
+ end
80
+ "#{context}#{command_name}"
81
+ end
82
+
83
+ def generate_completion_string(command, class_options, context_name, executable_name, style)
84
+ builder = ''
85
+ if command.is_a? ParsedSubcommand
86
+ class_options = (class_options + command.class_options).uniq
87
+ builder += map_to_completion_string(command.commands, context_name, class_options, executable_name)
88
+ builder += create_completion_string(read_template(style, :subcommand), binding)
89
+ else
90
+ builder += create_completion_string(read_template(style, :command), binding)
91
+ end
92
+ builder
93
+ end
94
+
95
+ # Recursively generate a command map based off
96
+ # of the commands and subcommands passed in.
97
+ #
98
+ # The [command_map] is a map of [String]s to [Thor::Command] objects,
99
+ # while the [subcommand_map] is a map of [String]s to [Thor] classes,
100
+ # usually your own CLI classes that subclass [Thor]
101
+ #
102
+ # @param command_map [Hash<String, Thor::Command>]
103
+ # a map to recursively generate a completion layout
104
+ # @param subcommand_map [Hash<String, Class < Thor>]
105
+ # a map indicating the subcommands and their respective classes
106
+ def recursively_find_commands(command_map, subcommand_map)
107
+ map = Hash[command_map.map { |k, v| [v, subcommand_map[k]] }]
108
+ map.map do |command, subcommand_class|
109
+ if subcommand_class.nil?
110
+ ancestor_name = command.ancestor_name if command.respond_to? :ancestor_name
111
+ ParsedCommand.new(ancestor_name, command.description, command.name, command.options.values)
112
+ else
113
+ commands = recursively_find_commands subcommand_class.commands, subcommand_class.subcommand_classes
114
+ ParsedSubcommand.new(command.name, command.description, commands, subcommand_class.class_options.values)
115
+ end
116
+ end
117
+ end
118
+
119
+ # Top level method to begin the recursive map generation
120
+ # This is needed because we don't have a 'top' level
121
+ # command to wrap everything under.
122
+ #
123
+ # This simplifies the rest of the code.
124
+ #
125
+ # (see #recursively_find_commands) for more documentation
126
+ def create_command_map(command_map, subcommand_map)
127
+ command_map = recursively_find_commands command_map, subcommand_map
128
+ ParsedSubcommand.new(nil, '', command_map, [])
129
+ end
130
+
131
+ # Helper method to load an [ERB] template
132
+ # and generate the corresponding [String]
133
+ #
134
+ # @param template [String] an ERB template
135
+ # @param bind [Binding] a binding to a context
136
+ def create_completion_string(template, bind)
137
+ template = ERB.new(template, nil, '-<>')
138
+ template.result(bind)
139
+ end
140
+
141
+ # Helper method to read an [ERB] template
142
+ # from a file and return it as a [String]
143
+ #
144
+ # @param name [Symbol] type of template to retrieve
145
+ # can be either :help, :subcommand, or :command
146
+ # @param style [Symbol] style of template to retrieve
147
+ # can be either :zsh or :bash
148
+ # @return [String] template string retrieved from erb file
149
+ def read_template(style, name)
150
+ style = style.is_a?(Symbol) ? style.to_s : style
151
+ name = name.is_a?(Symbol) ? name.to_s : name
152
+ erb_path = "erb_templates/#{style}/#{name}.erb"
153
+ File.read(File.join(__dir__, erb_path))
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,13 @@
1
+ function _<%= executable_name %><%= context_name %> {
2
+ _arguments \
3
+ <%- unless command.options.nil? -%>
4
+ <%- command.options.each do |option| -%>
5
+ "-<%= option.name%>=[<%= option.banner %>]"
6
+ "-<%= option.aliases[0]%>=[<%= option.banner %>]"
7
+ <%- end -%>
8
+ <%- end -%>
9
+ "-h[Show help information]" \
10
+ "--help[Show help information]" \
11
+ "1: :_commands" \
12
+ "*::arg:->args"/.
13
+ }
@@ -0,0 +1,19 @@
1
+ function _<%= executable_name %>_help {
2
+ <%- unless command.commands.empty? %>
3
+ function _commands {
4
+ local -a commands
5
+ commands=(
6
+ <%-# remove newlines and leading space on this loop -%>
7
+ <%- command.commands.each do |command| -%>
8
+ '<%= command.name %>:<%= command.description %>'
9
+ <%- end -%>
10
+ )
11
+ _describe 'command' commands
12
+ }
13
+ <%- end %>
14
+ _arguments \
15
+ "-h[Show help information]" \
16
+ "--help[Show help information]" \
17
+ "1: :_commands" \
18
+ "*::arg:->args"/.
19
+ }
@@ -0,0 +1,35 @@
1
+ function _<%= executable_name %><%= context_name %> {
2
+ local line
3
+ <%- unless command.commands.empty? %>
4
+ function _commands {
5
+ local -a commands
6
+ commands=(
7
+ <%-# remove newlines and leading space on this loop -%>
8
+ <%- command.commands.each do |command| -%>
9
+ '<%= command.name %>:<%= command.description %>'
10
+ <%- end -%>
11
+ )
12
+ _describe 'command' commands
13
+ }
14
+ <%- end %>
15
+ _arguments \
16
+ <%- unless class_options.nil? -%>
17
+ <%- class_options.each do |option| -%>
18
+ <%- option.aliases.each do |al| -%>
19
+ "-<%= al %>=[<%= option.banner %>]"
20
+ <%- end -%>
21
+ "--<%= option.name%>=[<%= option.banner %>]"
22
+ <%- end -%>
23
+ <%- end -%>
24
+ "-h[Show help information]" \
25
+ "--help[Show help information]" \
26
+ "1: :_commands" \
27
+ "*::arg:->args"/.
28
+ case $line[1] in
29
+ <%- command.commands.each do |command| -%>
30
+ <%= command.name %>)
31
+ _<%= executable_name %><%= context_name %>_<%= command.name %>
32
+ ;;
33
+ <%- end -%>
34
+ esac
35
+ }
@@ -0,0 +1,12 @@
1
+ module Fylla
2
+ class ParsedCommand
3
+ attr_accessor :ancestor_name, :description, :name, :options
4
+
5
+ def initialize(ancestor_name, description, name, options)
6
+ @ancestor_name = ancestor_name
7
+ @description = description
8
+ @name = name
9
+ @options = options
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Fylla
2
+ class ParsedSubcommand
3
+ attr_accessor :name, :description, :commands, :class_options
4
+
5
+ def initialize(name, description, commands, class_options)
6
+ @name = name
7
+ @description = description
8
+ @commands = commands
9
+ @class_options = class_options
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Fylla
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/fylla.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'fylla/version'
2
+ require 'fylla/completion_generator'
3
+ require 'fylla/parsed_command'
4
+ require 'fylla/parsed_subcommand'
5
+ require 'thor'
6
+
7
+ #
8
+ # Top level module for the Fylla project.
9
+ # Contains one method for initializing Fylla
10
+ #
11
+ module Fylla
12
+ def self.load(executable_name = nil)
13
+ @executable_name = executable_name || nil
14
+ ::Thor.prepend Fylla::Thor::CompletionGenerator
15
+ end
16
+
17
+ def self.zsh_completion(binding, executable_name = @executable_name)
18
+ binding.class.zsh_completion(executable_name)
19
+ end
20
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fylla
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tyler Thrailkill
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-01-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest-hooks
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.5.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.5.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 0.19.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 0.19.0
83
+ description: "\n Fylla generates zsh and bash autocomplete scripts for Thor CLI applications.\n
84
+ \ "
85
+ email:
86
+ - tyler.b.thrailkill@gmail.com
87
+ executables:
88
+ - fylla
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - Rakefile
95
+ - bin/console
96
+ - bin/setup
97
+ - exe/fylla
98
+ - fylla.gemspec
99
+ - lib/fylla.rb
100
+ - lib/fylla/completion_generator.rb
101
+ - lib/fylla/erb_templates/zsh/command.erb
102
+ - lib/fylla/erb_templates/zsh/help.erb
103
+ - lib/fylla/erb_templates/zsh/subcommand.erb
104
+ - lib/fylla/parsed_command.rb
105
+ - lib/fylla/parsed_subcommand.rb
106
+ - lib/fylla/version.rb
107
+ homepage: https://github.com/snowe2010/fylla
108
+ licenses:
109
+ - MIT
110
+ metadata:
111
+ yard.run: yri
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.6.14.1
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Adds functions for generating autocomplete scripts for Thor applications
132
+ test_files: []