fylla 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []