menu_commander 0.1.6 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac6321af9d45e46d217819d6659c88786ad23f6946d8c7f63076ed98ad8c3ba5
4
- data.tar.gz: 650c78d949042c8a3651edad05bc82491fcd7b7095fc4b638b4e52dcfe9b0b74
3
+ metadata.gz: fc729b17a7ba7e6fbba64302b2323cd073d9ea2a69b633f8ddbaf24890ff00a7
4
+ data.tar.gz: 82afd7ef1013dd8438b53da908a2841acf36a5bfe39148b7fd357e85a9548ef1
5
5
  SHA512:
6
- metadata.gz: d53c7fc17bd0ee211262624b0973d49eff0c433d5b819847989b211d452514e531d3183a662a9d1b878c916086a92b57ed3359d6b624a414cef470ee8f8410c2
7
- data.tar.gz: 446c8c2a2f6d99af790e1f011251a6005a83173aec102b2b6bf792bcce57bd9dd343a9d5488ce969da5a1f956203f22cf475a056234092b737786f6b32a3ef40
6
+ metadata.gz: 88bc9315c1c6502f1d3c40d12880a0b80e54bda56705fa00509a1b5aa6daacc398e67a4f241f0dbf45100dde6610803561842a58ed66ea440006a5cddbf27699
7
+ data.tar.gz: 85747cfd5579c748491c5526477b428b44c8458cb5cf6f8bbf29d0e05e06b4ed57bffc3616f21f50c286c3444c846a0e81e6bb0eb123de84d3c40339c4fb65ec
data/README.md CHANGED
@@ -14,14 +14,14 @@ Easily create menus for any command line tool using simple YAML configuration.
14
14
  * [Installation](#installation)
15
15
  * [Usage](#usage)
16
16
  * [Menu Navigation](#menu-navigation)
17
- * [Menu Configuration Features](#menu-configuration-features)
17
+ * [Menu Definition](#menu-definition)
18
18
  * [Minimal menu requirements](#minimal-menu-requirements)
19
19
  * [Argument sub-menus](#argument-sub-menus)
20
20
  * [Free text input](#free-text-input)
21
21
  * [Nested menus](#nested-menus)
22
- * [Header text](#header-text)
23
22
  * [Split menu into several files](#split-menu-into-several-files)
24
23
  * [Multi-line commands](#multi-line-commands)
24
+ * [Menu Options](#menu-options)
25
25
  * [Menu File Location](#menu-file-location)
26
26
 
27
27
  ---
@@ -81,7 +81,7 @@ $ menu some-other-file
81
81
 
82
82
 
83
83
 
84
- Menu Configuration Features
84
+ Menu Definition
85
85
  --------------------------------------------------
86
86
 
87
87
  All features have an example configuration in the
@@ -199,20 +199,6 @@ menu:
199
199
  > See: [examples/args-nested.yml](examples/args-nested.yml)
200
200
 
201
201
 
202
- ### Header text
203
-
204
- Use the `header` option to display a sentence or a multi-line paragraph when
205
- the menu is started. The header string supports [colsole color markers][1]:
206
-
207
- ```yaml
208
- header: |-
209
- Welcome to this !txtgrn!basic menu
210
- !bldred!Multiline!txtrst! headers are allowed
211
- ```
212
-
213
- > See: [examples/header.yml](examples/header.yml)
214
-
215
-
216
202
  ### Split menu into several files
217
203
 
218
204
  Each menu configuration file can include any number of additional YAML
@@ -276,6 +262,47 @@ menu:
276
262
  > See: [examples/multiline.yml](examples/multiline.yml)
277
263
 
278
264
 
265
+ Menu Options
266
+ --------------------------------------------------
267
+
268
+ You can tweak several aspects of the menu by adding an `options` section
269
+ in your YAML file.
270
+
271
+ ```yaml
272
+ options:
273
+ # Show header text
274
+ header: Hello
275
+
276
+ # Marker to show as the suffix of items that have submenus
277
+ # Use false to disable
278
+ submenu_marker: " ..."
279
+
280
+ # Menu selection marker
281
+ select_marker: ">"
282
+
283
+ # Menu title marker
284
+ title_marker: "-"
285
+
286
+ # When a menu has more items than page_size, add pagiation
287
+ # Default 10
288
+ page_size: 2
289
+
290
+ # When to show search filter
291
+ # yes = always show
292
+ # no = never show
293
+ # auto = show only when there aare more items than page_size (default)
294
+ # <number> = show only when there are more items than <number>
295
+ filter: yes
296
+
297
+ # When arg lists generate one item only it is auto-selected by default.
298
+ # Set this to false to disable this behavior
299
+ auto_select: false
300
+ ```
301
+
302
+ > See: [examples/optons.yml](examples/options.yml)
303
+
304
+
305
+
279
306
  Menu File Location
280
307
  --------------------------------------------------
281
308
 
data/bin/menu CHANGED
@@ -19,7 +19,7 @@ rescue MenuCommander::Exit => e
19
19
  rescue MenuCommander::MenuNotFound => e
20
20
  say! "#{e.message}"
21
21
  if e.paths and e.config
22
- message = "Looked for !txtgrn!#{e.config}.yml!txtrst! in"
22
+ message = "Looked for !txtgrn!#{e.config}!txtrst! in"
23
23
  if e.paths.size == 1
24
24
  message += " !txtgrn!#{e.paths.first}"
25
25
  say! message
@@ -4,24 +4,25 @@ module MenuCommander
4
4
  class Command < MisterBin::Command
5
5
  help "Menu Commander"
6
6
 
7
- usage "menu [CONFIG --dry --loop]"
7
+ usage "menu [CONFIG --loop (--dry|--confirm)]"
8
8
  usage "menu (-h|--help|--version)"
9
9
 
10
10
  option "-d --dry", "Dry run - do not execute the command at the end, just show it"
11
11
  option "-l --loop", "Reopen the menu after executing the selected command"
12
+ option "-c --confirm", "Show the command before execution and ask for confirmation"
12
13
  option "--version", "Show version number"
13
14
 
14
- param "CONFIG", "The name of the menu config file without the .yml extension [default: menu]"
15
+ param "CONFIG", "The name of the menu config file with or without the .yml extension [default: menu]"
15
16
 
16
17
  example "menu --dry"
17
- example "menu production --loop"
18
+ example "menu production --loop --confirm"
18
19
  example "menu -ld"
19
20
 
20
21
  attr_reader :last_command
21
22
 
22
23
  def run
23
24
  verify_sanity
24
- say "#{menu.header}\n" if menu.header
25
+ say "#{menu.options.header}\n" if menu.options.header
25
26
 
26
27
  if args['--loop']
27
28
  run_looped_menu
@@ -53,7 +54,10 @@ module MenuCommander
53
54
  command = menu.call
54
55
  @last_command = command
55
56
 
56
- if args['--dry']
57
+ if args['--confirm']
58
+ say "$ !txtpur!#{command}".strip
59
+ system command if prompt.yes? "Execute?"
60
+ elsif args['--dry']
57
61
  say "$ !txtpur!#{command}".strip
58
62
  else
59
63
  system command
@@ -66,7 +70,7 @@ module MenuCommander
66
70
 
67
71
  def menu_file!
68
72
  menu_paths.each do |dir|
69
- file = "#{dir}/#{config}.yml"
73
+ file = "#{dir}/#{config}"
70
74
  return file if File.exist? file
71
75
  end
72
76
  nil
@@ -81,7 +85,13 @@ module MenuCommander
81
85
  end
82
86
 
83
87
  def config
84
- config = args['CONFIG'] || 'menu'
88
+ result = args['CONFIG'] || 'menu'
89
+ result += ".yml" unless result.end_with?('.yml')
90
+ result
91
+ end
92
+
93
+ def prompt
94
+ @prompt ||= TTY::Prompt.new
85
95
  end
86
96
  end
87
97
  end
@@ -18,7 +18,7 @@ module MenuCommander
18
18
  class ExitMenu < Interrupt
19
19
  # :nocov:
20
20
  def initialize(message=nil)
21
- super (message || "> Exit")
21
+ super (message || "Goodbye")
22
22
  end
23
23
  # :nocov:
24
24
  end
@@ -24,8 +24,8 @@ module MenuCommander
24
24
 
25
25
  end
26
26
 
27
- def header
28
- config['header']
27
+ def options
28
+ @options ||= MenuOptions.new(config['options'])
29
29
  end
30
30
 
31
31
  private
@@ -70,9 +70,13 @@ module MenuCommander
70
70
  end
71
71
 
72
72
  def get_opts_type(opts)
73
- return :free_text if !opts
74
- return :static if opts.is_a? Array and opts.size == 1
75
- :menu
73
+ if !opts
74
+ :free_text
75
+ elsif options.auto_select and opts.is_a? Array and opts.size == 1
76
+ :static
77
+ else
78
+ :menu
79
+ end
76
80
  end
77
81
 
78
82
  def get_opts(key)
@@ -106,7 +110,6 @@ module MenuCommander
106
110
  end
107
111
  end
108
112
 
109
-
110
113
  def ask(title)
111
114
  prompt.ask "> #{title}:"
112
115
 
@@ -117,10 +120,36 @@ module MenuCommander
117
120
 
118
121
  end
119
122
 
120
- def select(options, title=nil)
121
- title = title ? "> #{title}:" : ">"
122
- enable_filter = options.size > 10
123
- prompt.select title, options, symbols: { marker: '>' }, per_page: 10, filter: enable_filter
123
+ def apply_suffix(choices)
124
+ choices.map do |key, value|
125
+ key = "#{key}#{options.submenu_marker}" if value.is_a? Hash
126
+ [key, value]
127
+ end.to_h
128
+ end
129
+
130
+ def enable_filter?(choices)
131
+ if options.filter === true
132
+ true
133
+ elsif options.filter === false
134
+ false
135
+ elsif options.filter.is_a? Numeric
136
+ choices.size > options.filter
137
+ else
138
+ choices.size > options.page_size
139
+ end
140
+ end
141
+
142
+ def select(choices, title=nil)
143
+ title = title ? "#{options.title_marker} #{title}:" : options.title_marker
144
+ choices = apply_suffix choices if options.submenu_marker
145
+ select! choices, title
146
+ end
147
+
148
+ def select!(choices, title)
149
+ prompt.select title, choices,
150
+ symbols: { marker: options.select_marker },
151
+ per_page: options.page_size,
152
+ filter: enable_filter?(choices)
124
153
 
125
154
  rescue TTY::Reader::InputInterrupt
126
155
  # :nocov:
@@ -0,0 +1,31 @@
1
+ module MenuCommander
2
+ class MenuOptions
3
+ attr_reader :options
4
+
5
+ def initialize(options)
6
+ options ||= {}
7
+ options.transform_keys! &:to_sym
8
+ @options = default_options.merge options
9
+ end
10
+
11
+ def default_options
12
+ @default_options ||= {
13
+ auto_select: true,
14
+ filter: 'auto',
15
+ header: false,
16
+ page_size: 10,
17
+ select_marker: "⯈",
18
+ submenu_marker: " ⯆",
19
+ title_marker: "◾",
20
+ }
21
+ end
22
+
23
+ def method_missing(method, *_args, &_block)
24
+ respond_to?(method) ? options[method] : super
25
+ end
26
+
27
+ def respond_to_missing?(method_name, include_private=false)
28
+ options.has_key?(method_name) || super
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ # :nocov:
2
+
3
+ # Required for Ruby < 2.5
4
+ if !{}.respond_to? :transform_keys!
5
+ class Hash
6
+ def transform_keys!
7
+ keys.each { |key| self[yield(key)] = delete(key) }
8
+ self
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,3 @@
1
1
  module MenuCommander
2
- VERSION = "0.1.6"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,4 +1,6 @@
1
+ require 'menu_commander/polyfills/hash'
1
2
  require 'menu_commander/exceptions'
3
+ require 'menu_commander/menu_options'
2
4
  require 'menu_commander/menu'
3
5
  require 'menu_commander/command'
4
6
  require 'menu_commander/cli'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: menu_commander
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-20 00:00:00.000000000 Z
11
+ date: 2019-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mister_bin
@@ -80,6 +80,8 @@ files:
80
80
  - lib/menu_commander/command.rb
81
81
  - lib/menu_commander/exceptions.rb
82
82
  - lib/menu_commander/menu.rb
83
+ - lib/menu_commander/menu_options.rb
84
+ - lib/menu_commander/polyfills/hash.rb
83
85
  - lib/menu_commander/version.rb
84
86
  homepage: https://github.com/dannyben/menu_commander
85
87
  licenses: