menu_commander 0.0.1

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
+ SHA256:
3
+ metadata.gz: '09d63d573439372dd5e017940ded720734eef31f0eea6cc290ff0605328a0118'
4
+ data.tar.gz: 3b6e7e0a01a17463289c8390581cf899498281c98ccb1eb6fcd88535462db953
5
+ SHA512:
6
+ metadata.gz: b496ffd6d0b7734a906091ce1c90e685ba691f3415108bca93c6766caeaca7153c39251ebe4c9ca690b6b51d845242d42b4ce9794d0cd4d84b23d5d024c5a671
7
+ data.tar.gz: 47c792e570005e6e47746d7495ee138b80a5d8d9330f92d1a22399772cd1687d78f1a45ce2f92a628861b8064b2f97b0276bdad5495ed689a76752e0303e9ac0
data/README.md ADDED
@@ -0,0 +1,147 @@
1
+ Menu Commander
2
+ ==================================================
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/menu_commander.svg)](https://badge.fury.io/rb/menu_commander)
5
+ [![Build Status](https://travis-ci.com/DannyBen/menu_commander.svg?branch=master)](https://travis-ci.com/DannyBen/menu_commander)
6
+ [![Maintainability](https://api.codeclimate.com/v1/badges/.../maintainability)](https://codeclimate.com/github/DannyBen/menu_commander/maintainability)
7
+
8
+ ---
9
+
10
+ Easily create menus for any command line tool using simple YAML configuration.
11
+
12
+ ---
13
+
14
+ Installation
15
+ --------------------------------------------------
16
+
17
+ $ gem install menu_commander
18
+
19
+
20
+
21
+ Usage
22
+ --------------------------------------------------
23
+
24
+ Menu Commander adds the `menu` command line tool to your path. When running
25
+ it without arguments, it will look for a `menu.yml` file in the current
26
+ directory, and will provide you with a menu to execute any shell command.
27
+
28
+ A basic menu configuration file looks like this:
29
+
30
+ ```yaml
31
+ # menu.yml
32
+
33
+ # Using %{variables} in a command will prompt for an input when executed
34
+ menu:
35
+ hello: echo hello
36
+ hi: echo hi %{name}
37
+
38
+ # Define sub menus for any %{variable} that was defined in the command
39
+ args:
40
+ name:
41
+ - Harry
42
+ - Lloyd
43
+ ```
44
+
45
+ Running it, looks like this:
46
+
47
+ ![Demo](/demo/demo.gif)
48
+
49
+
50
+ Features
51
+ --------------------------------------------------
52
+
53
+ All features have an example configuration in the
54
+ [examples folder](examples). To run an example, simply execute
55
+ `menu EAXMPLE_NAME` form within the examples folder, where `EXAMPLE_NAME`
56
+ is the name of the YAML file without the extension.
57
+
58
+ ### Minimal menu requirements
59
+
60
+ The only requirement for a minimal menu is to have a `menu` definition
61
+ with `key: command` to run.
62
+
63
+ ```yaml
64
+ # examples/minimal.yml
65
+ menu:
66
+ hello: echo hello
67
+ whoami: whoami
68
+ ```
69
+
70
+ ### Argument sub-menus
71
+
72
+ Using `%{variables}` in a command will prompt for an input when executed. The
73
+ sub-menu for that input is specified in the `args` definition.
74
+
75
+ ```yaml
76
+ # examples/args-array.yml
77
+ menu:
78
+ server: rails server --env %{environment}
79
+ test: RAILS_ENV=%{environment} rspec
80
+
81
+ args:
82
+ environment:
83
+ - staging
84
+ - production
85
+ ```
86
+
87
+ Using `key: value` pairs in the `args` menu will create a sub-menu with
88
+ labels that are different from their substituted value:
89
+
90
+ ```yaml
91
+ # examples/args-hash.yml
92
+ menu:
93
+ server: rails server --env %{environment}
94
+ test: RAILS_ENV=%{environment} rspec
95
+
96
+ args:
97
+ environment:
98
+ Staging Environment: staging
99
+ Production Environment: production
100
+ ```
101
+
102
+ In order to obtain the sub-menu items from a shell command, simply provide
103
+ the command to run, instead of providing the menu options. The command is
104
+ expected to provide newline-delimited output.
105
+
106
+ ```yaml
107
+ # examples/args-shell.yml
108
+ menu:
109
+ show: cat %{file}
110
+ edit: vi %{file}
111
+
112
+ args:
113
+ file: ls
114
+ ```
115
+
116
+ ### Free text input
117
+
118
+ When using a `%{variable}` that does not have a corresponding definition in
119
+ the `args` section, you will simply be prompted for a free text input:
120
+
121
+ ```yaml
122
+ # examples/args-free-text.yml
123
+ menu:
124
+ release:
125
+ echo %{version} > version.txt &&
126
+ git tag v%{version}
127
+ ```
128
+
129
+ ### Nested menus
130
+
131
+ You can nest as many menu levels as you wish under the menu definition.
132
+
133
+ ```yaml
134
+ # examples/nested.yml
135
+ menu:
136
+ docker:
137
+ images: docker images ls
138
+ containers: docker ps -a
139
+ stack:
140
+ deploy: docker stack deploy -c docker-compose.yml mystack
141
+ list: docker stack ls
142
+
143
+ git:
144
+ status: git status
145
+ branch: git branch
146
+ ```
147
+
data/bin/menu ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ require 'menu_commander'
3
+ require 'colsole'
4
+ include Colsole
5
+
6
+ router = MenuCommander::CLI.router
7
+
8
+ begin
9
+ exit router.run ARGV
10
+ rescue MenuCommander::MenuNotFound => e
11
+ say! "!txtred!#{e.message}"
12
+ exit 1
13
+ rescue => e
14
+ puts e.backtrace.reverse if ENV['DEBUG']
15
+ say! "!txtred!#{e.class}: #{e.message}"
16
+ exit 1
17
+ end
@@ -0,0 +1,13 @@
1
+ require 'mister_bin'
2
+
3
+ module MenuCommander
4
+ class CLI
5
+ def self.router
6
+ router = MisterBin::Runner.new version: VERSION,
7
+ header: "CLI Menu Generator"
8
+
9
+ router.route_all to: Command
10
+ router
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,43 @@
1
+ require 'mister_bin'
2
+ require 'colsole'
3
+
4
+ module MenuCommander
5
+ class Command < MisterBin::Command
6
+ include Colsole
7
+
8
+ help "Execute the menu"
9
+ usage "menu [CONFIG --dry]"
10
+ usage "menu (-h|--help)"
11
+ option "-d --dry", "Dry run. Do not execute the command at the end, just show it."
12
+ param "CONFIG", "The name of the menu config file without the .yml extension [default: menu]"
13
+
14
+ def run
15
+ raise MenuNotFound unless File.exist? menu_file
16
+
17
+ if args['--dry']
18
+ say "$ !txtpur!#{command}"
19
+ else
20
+ exec command
21
+ end
22
+ end
23
+
24
+ def menu
25
+ @menu ||= Menu.new menu_file
26
+ end
27
+
28
+ def command
29
+ @command ||= menu.call
30
+ end
31
+
32
+ private
33
+
34
+ def menu_file
35
+ "#{config}.yml"
36
+ end
37
+
38
+ def config
39
+ config = args['CONFIG'] || 'menu'
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,11 @@
1
+ module MenuCommander
2
+ class Error < StandardError; end
3
+
4
+ class MenuNotFound < Error
5
+ # :nocov: - covered by external process
6
+ def initialize(message="Could not find menu configuration file")
7
+ super
8
+ end
9
+ # :nocov:
10
+ end
11
+ end
@@ -0,0 +1,74 @@
1
+ require 'yaml'
2
+ require 'tty/prompt'
3
+
4
+ module MenuCommander
5
+ class Menu
6
+ attr_reader :config
7
+
8
+ def initialize(config)
9
+ config = YAML.load_file config if config.is_a? String
10
+ @config = config
11
+ end
12
+
13
+ def call(menu = nil)
14
+ menu ||= config['menu']
15
+ response = select menu
16
+ if response.is_a? String
17
+ params = {}
18
+ placeholders(response).each do |key|
19
+ params[key.to_sym] = get_user_response key
20
+ end
21
+
22
+ response % params
23
+ else
24
+ call response
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def placeholders(template)
31
+ template.scan(/%{([^}]+)}/).flatten.uniq
32
+ end
33
+
34
+ def args
35
+ config['args']
36
+ end
37
+
38
+ def get_user_response(key)
39
+ opts = args ? args[key] : nil
40
+ opts = opts.is_a?(String) ? `#{opts}`.split("\n") : opts
41
+
42
+ if opts
43
+ opts.size == 1 ? opts[0] : select(opts, key)
44
+ else
45
+ ask(key)
46
+ end
47
+ end
48
+
49
+ def prompt
50
+ @prompt ||= TTY::Prompt.new
51
+ end
52
+
53
+ def ask(title)
54
+ prompt.ask "> #{title}:"
55
+ rescue TTY::Reader::InputInterrupt
56
+ # :nocov:
57
+ puts "\nGoodbye"
58
+ exit
59
+ # :nocov:
60
+ end
61
+
62
+ def select(options, title = nil)
63
+ title = title ? "> #{title}:" : ">"
64
+ menu_config = { marker: '>', per_page: 10 }
65
+ menu_config['filter'] = true if options.size > 10
66
+ prompt.select title, options, menu_config
67
+ rescue TTY::Reader::InputInterrupt
68
+ # :nocov:
69
+ puts "\nGoodbye"
70
+ exit
71
+ # :nocov:
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,3 @@
1
+ module MenuCommander
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,6 @@
1
+ require 'menu_commander/exceptions'
2
+ require 'menu_commander/menu'
3
+ require 'menu_commander/command'
4
+ require 'menu_commander/cli'
5
+
6
+ require 'byebug' if ENV['BYEBUG']
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: menu_commander
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Danny Ben Shitrit
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-04-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mister_bin
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: colsole
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: tty-prompt
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.18'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.18'
55
+ description: Easily create menus for any command line tool using simple YAML configuration
56
+ email: db@dannyben.com
57
+ executables:
58
+ - menu
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - README.md
63
+ - bin/menu
64
+ - lib/menu_commander.rb
65
+ - lib/menu_commander/cli.rb
66
+ - lib/menu_commander/command.rb
67
+ - lib/menu_commander/exceptions.rb
68
+ - lib/menu_commander/menu.rb
69
+ - lib/menu_commander/version.rb
70
+ homepage: https://github.com/dannyben/menu_commander
71
+ licenses:
72
+ - MIT
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 2.3.0
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubygems_version: 3.0.3
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: Create menus for any CLI tool
93
+ test_files: []