menutree 0.0.4 → 0.1.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.
data/.gitignore CHANGED
@@ -1 +1 @@
1
- pkg/
1
+ *.gem
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Menutree
2
2
 
3
- Menutree is a framework for presenting a recursive menu shell on the command
3
+ Menutree is a framework for presenting a recursive Read-Eval-Print Loop (REPL) shell on the command
4
4
  line, inspired by the CLI found in Cisco IOS and other similar products.
5
5
  Menutree lets users issue commands via an interactive nested shell interface,
6
6
  and also directly from the command line.
@@ -11,26 +11,24 @@ readline support are all built in.
11
11
 
12
12
  ## Example:
13
13
 
14
- Given a hypothetical program 'ticker' that uses the Menutree gem to manage a list of
15
- tickets, a sample interaction might look like:
14
+ Given a hypothetical program 'ticket' that uses the Menutree gem to manage a list of
15
+ tickets (such a program is included in `examples/`), a sample interaction might look like:
16
16
 
17
17
  <pre>
18
- $ ticker
19
- > init
20
- Ticker created an empty ticket database
21
- > add "Do a little dance"
22
- Ticket "Do a little dance" added as ticket 213
23
- > rm
24
- rm> 213
25
- Ticket 213 ("Do a little dance") removed
26
- rm> ..
18
+ $ ruby ticket.rb
19
+ > action_one
20
+ One
21
+ > submenu_one
22
+ /submenu_one> action_one
23
+ Unknown command 'action_one'
24
+ /submenu_one> ..
27
25
  > exit
28
26
  </pre>
29
27
 
30
28
  Commands could also be run from the shell:
31
29
 
32
30
  <pre>
33
- $ ticker add "Make a little love"
31
+ $ rubyticke add "Make a little love"
34
32
  Ticket "Make a little love" added as ticket 214
35
33
  </pre>
36
34
 
data/Rakefile CHANGED
@@ -2,23 +2,6 @@ require 'rake'
2
2
  require 'rake/testtask'
3
3
  require 'rcov/rcovtask'
4
4
 
5
- begin
6
- require 'jeweler'
7
- Jeweler::Tasks.new do |s|
8
- s.name = "menutree"
9
- s.summary = "a simple hierachical command line shell"
10
- s.description = "Menutree is a framework for presenting a recursive menu shell on the command
11
- line, inspired by the CLI found in Cisco IOS and similar products"
12
- s.email = "mat@geeky.net"
13
- s.homepage = "http://github.com/mtrudel/menutree"
14
- s.authors = ["Mat Trudel", "Grant McInnes"]
15
- s.add_dependency 'activesupport'
16
- end
17
- Jeweler::GemcutterTasks.new
18
- rescue LoadError
19
- puts "Jeweler not available. Install it with: gem install jeweler"
20
- end
21
-
22
5
  Rake::TestTask.new do |t|
23
6
  t.libs << 'lib'
24
7
  t.pattern = 'test/**/*_test.rb'
@@ -0,0 +1,11 @@
1
+ leaf do |tree|
2
+ desc "This is action one's help"
3
+ def action_one(*args)
4
+ puts "This is action one, called with: #{args.join ' '}"
5
+ end
6
+
7
+ desc "This is action two's help"
8
+ def action_two(*args)
9
+ puts "This is action two, called with: #{args.join ' '}"
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ leaf do |tree|
2
+ desc "This is action one's help inside submenu one"
3
+ def action_one(*args)
4
+ puts "This is action one in submenu one, called with: #{args.join ' '}"
5
+ end
6
+
7
+ desc "This is action two's help inside submenu one"
8
+ def action_two(*args)
9
+ puts "This is action two in submenu one, called with: #{args.join ' '}"
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ leaf do |tree|
2
+ desc "This is action one's help inside submenu two"
3
+ def action_one(*args)
4
+ puts "This is action one in submenu two, called with: #{args.join ' '}"
5
+ end
6
+
7
+ desc "This is action two's help inside submenu one"
8
+ def action_two(*args)
9
+ puts "This is action two in submenu two, called with: #{args.join ' '}"
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'menutree'
5
+
6
+ MenuTree::Tree.new(File.join(File.dirname(__FILE__), 'commands')).repl(ARGV)
@@ -1,5 +1,5 @@
1
- $:.unshift(File.dirname(__FILE__)) unless
2
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
1
+ $:.unshift(File.join(File.dirname(__FILE__), 'menutree')) unless
2
+ $:.include?(File.join(File.dirname(__FILE__), 'menutree')) || $:.include?(File.expand_path(File.join(File.dirname(__FILE__), 'menutree')))
3
3
 
4
- require 'base'
4
+ require 'tree'
5
5
 
@@ -0,0 +1,26 @@
1
+ module MenuTree
2
+ INDENT = "\t"
3
+ COMMAND_WIDTH = -12
4
+ BUILTINS = {
5
+ "help" => "Displays this message",
6
+ "quit" => "Quits this session",
7
+ ".." => "Goes up a level in the menu (or quits if at the root)",
8
+ }
9
+
10
+ module Help
11
+ def display_help
12
+ display_help_section("Built-in commands", BUILTINS)
13
+ display_help_section("Leaf commands", @leaf.commands)
14
+ display_help_section("Submenus", submenus)
15
+ end
16
+
17
+ def display_help_section(section, contents, indent = 0)
18
+ puts INDENT*indent + section
19
+ contents.each do |command, description|
20
+ puts INDENT*(indent+1) + sprintf("%#{COMMAND_WIDTH}s %s", command, description)
21
+ end
22
+ puts ""
23
+ end
24
+ end
25
+ end
26
+
@@ -0,0 +1,23 @@
1
+ module MenuTree
2
+ class Leaf
3
+ attr_accessor :commands
4
+
5
+ def initialize(parent_tree)
6
+ @parent_tree = parent_tree
7
+ @commands = {}
8
+ @curent_description = ""
9
+ end
10
+
11
+ def desc(desc)
12
+ @current_description = desc
13
+ end
14
+
15
+ def singleton_method_added(symbol)
16
+ @commands[symbol] = @current_description
17
+ end
18
+
19
+ def leaf(&block)
20
+ self.instance_exec(@parent_tree, &block) if block_given?
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,73 @@
1
+ require 'readline'
2
+ require 'active_support'
3
+ require 'leaf'
4
+ require 'help'
5
+
6
+ module MenuTree
7
+ class Tree
8
+ include Help
9
+ attr_accessor :directory
10
+ attr_accessor :prompt
11
+ attr_accessor :leaf
12
+
13
+ def initialize(directory, parent = "")
14
+ @directory = directory
15
+ if parent.is_a? String
16
+ @prompt = parent
17
+ elsif !parent.prompt.empty?
18
+ @prompt = parent.prompt + "/" + File.basename(@directory)
19
+ else
20
+ @prompt = File.basename(@directory)
21
+ end
22
+
23
+ file = File.join(@directory, "leaf.rb")
24
+ @leaf = MenuTree::Leaf.new(self)
25
+ @leaf.instance_eval(File.read(file), file) if File.exists? file
26
+ end
27
+
28
+ def repl(cmds)
29
+ one_shot = true unless cmds.empty?
30
+ to_run = cmds.shift
31
+ while true do
32
+ Readline.completion_append_character = " "
33
+ Readline.completion_proc = Proc.new do |str|
34
+ commands(str)
35
+ end
36
+ if (to_run.nil?)
37
+ cmds = Readline.readline("#{@prompt}> ", true).split
38
+ to_run = cmds.shift
39
+ end
40
+
41
+ # If it's a builtin, run it
42
+ if (to_run.nil?)
43
+ next
44
+ elsif (to_run == "help" or to_run == "?")
45
+ display_help
46
+ elsif (to_run == "quit")
47
+ exit
48
+ elsif (to_run == "..")
49
+ return
50
+ elsif File.directory?(File.join(@directory, to_run))
51
+ menu = MenuTree::Tree.new(File.join(@directory, to_run), self)
52
+ menu.repl(cmds)
53
+ else
54
+ @leaf.send to_run, cmds rescue puts "Unknown command #{to_run}"
55
+ end
56
+ to_run = nil
57
+ return if one_shot
58
+ end
59
+ end
60
+
61
+ def commands(prefix='')
62
+ (leaf_commands + submenus).select { |command| command =~ /^#{Regexp.escape(prefix)}/ }
63
+ end
64
+
65
+ def leaf_commands
66
+ @leaf.commands.keys.map { |x| x.to_s }
67
+ end
68
+
69
+ def submenus
70
+ Dir.new(@directory).select { |entry| entry =~ /^[^\.]/ and File.directory?(File.join(@directory, entry)) }
71
+ end
72
+ end
73
+ end
@@ -1,17 +1,10 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
4
- # -*- encoding: utf-8 -*-
5
-
6
1
  Gem::Specification.new do |s|
7
2
  s.name = %q{menutree}
8
- s.version = "0.0.4"
3
+ s.version = "0.1.1"
9
4
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
5
  s.authors = ["Mat Trudel", "Grant McInnes"]
12
- s.date = %q{2010-03-16}
13
- s.description = %q{Menutree is a framework for presenting a recursive menu shell on the command
14
- line, inspired by the CLI found in Cisco IOS and similar products}
6
+ s.date = %q{2011-01-05}
7
+ s.description = %q{Menutree is a framework for presenting a recursive REPL shell, inspired by the CLI found in Cisco IOS and similar products}
15
8
  s.email = %q{mat@geeky.net}
16
9
  s.extra_rdoc_files = [
17
10
  "README.md"
@@ -20,28 +13,19 @@ Gem::Specification.new do |s|
20
13
  ".gitignore",
21
14
  "README.md",
22
15
  "Rakefile",
23
- "VERSION",
24
- "lib/base.rb",
25
16
  "lib/menutree.rb",
17
+ "lib/menutree/tree.rb",
18
+ "lib/menutree/leaf.rb",
19
+ "lib/menutree/help.rb",
20
+ "examples/example.rb",
21
+ "examples/commands/leaf.rb",
22
+ "examples/commands/submenu_one/leaf.rb",
23
+ "examples/commands/submenu_two/leaf.rb",
26
24
  "menutree.gemspec"
27
25
  ]
28
26
  s.homepage = %q{http://github.com/mtrudel/menutree}
29
- s.rdoc_options = ["--charset=UTF-8"]
30
27
  s.require_paths = ["lib"]
31
- s.rubygems_version = %q{1.3.6}
32
- s.summary = %q{a simple hierachical command line shell}
33
-
34
- if s.respond_to? :specification_version then
35
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
36
- s.specification_version = 3
37
-
38
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
39
- s.add_runtime_dependency(%q<activesupport>, [">= 0"])
40
- else
41
- s.add_dependency(%q<activesupport>, [">= 0"])
42
- end
43
- else
44
- s.add_dependency(%q<activesupport>, [">= 0"])
45
- end
28
+ s.summary = %q{a simple hierachical REPL shell}
29
+ s.add_dependency(%q<activesupport>, [">= 0"])
46
30
  end
47
31
 
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: menutree
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 25
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
- - 0
8
- - 4
9
- version: 0.0.4
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
10
11
  platform: ruby
11
12
  authors:
12
13
  - Mat Trudel
@@ -15,24 +16,24 @@ autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2010-03-16 00:00:00 -04:00
19
+ date: 2011-01-05 00:00:00 -05:00
19
20
  default_executable:
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
22
23
  name: activesupport
23
24
  prerelease: false
24
25
  requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
25
27
  requirements:
26
28
  - - ">="
27
29
  - !ruby/object:Gem::Version
30
+ hash: 3
28
31
  segments:
29
32
  - 0
30
33
  version: "0"
31
34
  type: :runtime
32
35
  version_requirements: *id001
33
- description: |-
34
- Menutree is a framework for presenting a recursive menu shell on the command
35
- line, inspired by the CLI found in Cisco IOS and similar products
36
+ description: Menutree is a framework for presenting a recursive REPL shell, inspired by the CLI found in Cisco IOS and similar products
36
37
  email: mat@geeky.net
37
38
  executables: []
38
39
 
@@ -44,39 +45,48 @@ files:
44
45
  - .gitignore
45
46
  - README.md
46
47
  - Rakefile
47
- - VERSION
48
- - lib/base.rb
49
48
  - lib/menutree.rb
49
+ - lib/menutree/tree.rb
50
+ - lib/menutree/leaf.rb
51
+ - lib/menutree/help.rb
52
+ - examples/example.rb
53
+ - examples/commands/leaf.rb
54
+ - examples/commands/submenu_one/leaf.rb
55
+ - examples/commands/submenu_two/leaf.rb
50
56
  - menutree.gemspec
51
57
  has_rdoc: true
52
58
  homepage: http://github.com/mtrudel/menutree
53
59
  licenses: []
54
60
 
55
61
  post_install_message:
56
- rdoc_options:
57
- - --charset=UTF-8
62
+ rdoc_options: []
63
+
58
64
  require_paths:
59
65
  - lib
60
66
  required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
61
68
  requirements:
62
69
  - - ">="
63
70
  - !ruby/object:Gem::Version
71
+ hash: 3
64
72
  segments:
65
73
  - 0
66
74
  version: "0"
67
75
  required_rubygems_version: !ruby/object:Gem::Requirement
76
+ none: false
68
77
  requirements:
69
78
  - - ">="
70
79
  - !ruby/object:Gem::Version
80
+ hash: 3
71
81
  segments:
72
82
  - 0
73
83
  version: "0"
74
84
  requirements: []
75
85
 
76
86
  rubyforge_project:
77
- rubygems_version: 1.3.6
87
+ rubygems_version: 1.3.7
78
88
  signing_key:
79
89
  specification_version: 3
80
- summary: a simple hierachical command line shell
90
+ summary: a simple hierachical REPL shell
81
91
  test_files: []
82
92
 
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.0.4
@@ -1,86 +0,0 @@
1
- require 'readline'
2
- require 'active_support'
3
-
4
- class MenuTree
5
- attr_accessor :directory
6
- attr_accessor :parent
7
- attr_accessor :prompt
8
-
9
- def initialize(directory, parent = "")
10
- @directory = directory
11
- @parent = parent
12
- if @parent.is_a? self.class
13
- @prompt = @parent.prompt + "/" + File.basename(@directory)
14
- else
15
- @prompt = @parent
16
- end
17
- end
18
-
19
- def run_command(cmds)
20
- Readline.completion_append_character = " "
21
- Readline.completion_proc = Proc.new do |str|
22
- commands(str)
23
- end
24
-
25
- one_shot = true unless cmds.empty?
26
- to_run = cmds.shift
27
- while true do
28
- if (to_run.nil?)
29
- cmds = Readline.readline("#{@prompt}> ", true).split
30
- to_run = cmds.shift
31
- end
32
-
33
- # If it's a builtin, run it
34
- if (to_run.nil?)
35
- next
36
- elsif (to_run == "help" or to_run == "?")
37
- display_help
38
- elsif (to_run == "quit")
39
- exit
40
- elsif (to_run == "..")
41
- return
42
- elsif File.exists?(File.join(@directory, "#{to_run}.rb"))
43
- # If we have a .rb file, run it with the rest of cmd as arguments
44
- # TODO -- use .extend?
45
- require File.join(@directory, "#{to_run}")
46
- eval(to_run.camelize).new.run(cmds)
47
- elsif File.directory?(File.join(@directory, to_run))
48
- menu = MenuTree.new(File.join(@directory, to_run), self)
49
- menu.run_command(cmds)
50
- elsif File.exists?(File.join(@directory, "default.rb"))
51
- # TODO let default handle it, allowing us to have proxy menus
52
- else
53
- puts "Unknown command #{to_run}"
54
- end
55
- to_run = nil
56
- return if one_shot
57
- end
58
- end
59
-
60
- def commands(prefix='')
61
- completions = []
62
- Dir.new(@directory).each do |command|
63
- if command =~ /^[^\.]/ and command =~ /^#{Regexp.escape(prefix)}/ and File.file?(File.join(@directory, command))
64
- completions << File.basename(command, '.rb')
65
- end
66
- end
67
- completions
68
- end
69
-
70
- def display_help
71
- puts <<EOF
72
- Builtin commands:
73
- help:\t\t\t\tDisplays this message
74
- quit:\t\t\t\tQuits this session
75
- ..: \t\t\t\tGoes up a level in the menu (or quits if at the root)
76
-
77
- #{@parent} commands:
78
- EOF
79
-
80
- # TODO display some help for each submenu
81
- commands.each do |cmd|
82
- require File.join(@directory, "#{cmd}")
83
- puts " #{cmd}:\t\t\t\t#{eval(cmd.camelize).new.description}"
84
- end
85
- end
86
- end