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 +7 -0
- data/README.md +147 -0
- data/bin/menu +17 -0
- data/lib/menu_commander/cli.rb +13 -0
- data/lib/menu_commander/command.rb +43 -0
- data/lib/menu_commander/exceptions.rb +11 -0
- data/lib/menu_commander/menu.rb +74 -0
- data/lib/menu_commander/version.rb +3 -0
- data/lib/menu_commander.rb +6 -0
- metadata +93 -0
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
|
+
[](https://badge.fury.io/rb/menu_commander)
|
5
|
+
[](https://travis-ci.com/DannyBen/menu_commander)
|
6
|
+
[](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
|
+

|
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,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,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
|
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: []
|