dynmenu 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.
data/bin/dynmenu ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+ require 'yaml'
3
+ $subtle = true
4
+ $lines = 20
5
+ begin
6
+ require 'subtle/subtlext'
7
+ rescue LoadError
8
+ $subtle = false
9
+ end
10
+ require 'root_menu'
11
+ require 'command'
12
+ require 'style'
13
+ require 'editor'
14
+ require 'history'
15
+ require 'run_menu'
16
+
17
+ license = <<END_LICENSE
18
+ dynmenu - A dmenu wrapper written in Ruby
19
+ ---
20
+ Copyright (C) 2013 Joakim Reinert
21
+
22
+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
23
+
24
+ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
25
+
26
+ You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/
27
+
28
+ END_LICENSE
29
+
30
+ usage = <<END_USAGE
31
+ Usage: dynmenu [options] file
32
+ Options: -h --help : Show this help
33
+ -r : Open the menu as read only and static
34
+ -l <number> : Show max <number> lines in the menu (default=20)
35
+ File: : The menu file to be loaded and saved to.
36
+ It will be created if not existing.
37
+ END_USAGE
38
+
39
+ puts license
40
+
41
+ if ARGV.length > 4 || ARGV.length < 1 || ARGV.include?("-h") || ARGV.include?("--help")
42
+ puts usage
43
+ exit
44
+ elsif ARGV.include? "-l"
45
+ lines = ARGV[ARGV.index("-l") + 1]
46
+ if lines.to_i.to_s != lines || lines.to_i < 1
47
+ puts usage
48
+ exit
49
+ end
50
+ $lines = lines
51
+ else
52
+ lines_matcher = Regexp.new(/^-l(\d+)$/)
53
+ ARGV.each do |arg|
54
+ if arg.match lines_matcher
55
+ $lines = Regexp.last_match(1)
56
+ end
57
+ end
58
+ end
59
+
60
+ file = ARGV[ARGV.length - 1]
61
+ if File.exist? file
62
+ menu = YAML::load File.read(file)
63
+ else
64
+ menu = Root_Menu.new
65
+ end
66
+ $read_only = ARGV.include? "-r"
67
+ menu.execute
68
+ File.open(file, "w+") { |f| YAML::dump menu, f }
data/lib/command.rb ADDED
@@ -0,0 +1,174 @@
1
+ require 'item'
2
+
3
+ class Command
4
+ if $subtle
5
+ @@RE_COMMAND = Regexp.new(/^[+\^\*]*.+(\s[+\^\*])*(\s[@#][A-Za-z0-9_-]+)*$/)
6
+ @@RE_MODES = Regexp.new(/^[+\^\*]+$/)
7
+ @@RE_SEARCH = Regexp.new(/^[gs]\s+(.*)/)
8
+ @@RE_METHOD = Regexp.new(/^:\s*(.*)/)
9
+ @@RE_BROWSER = Regexp.new(/(chrom[e|ium]|iron|navigator|firefox|opera)/i)
10
+ end
11
+ @@RE_URI = Regexp.new(/^((w\s+((https?|ftp):\/\/)?)|(https?|ftp):\/\/)(?:[A-Z0-9-]+.)+[A-Z]{2,6}([\/?].+)?$/i)
12
+ @@RE_PROTO = Regexp.new(/^(http|https):\/\/.*/)
13
+
14
+ include Item
15
+
16
+ def initialize name, command = nil
17
+ @name = name
18
+ if $subtle
19
+ @tags = []
20
+ @views = []
21
+ @app = ""
22
+ @modes = ""
23
+ end
24
+
25
+ set_command command
26
+ end
27
+
28
+ def encode_with coder
29
+ coder['name'] = @name
30
+ coder['command'] = @command
31
+ if $subtle
32
+ coder['tags'] = @tags
33
+ coder['views'] = @views
34
+ coder['app'] = @app
35
+ coder['modes'] = @modes
36
+ end
37
+ end
38
+
39
+ def init_with coder
40
+ @name = coder['name']
41
+ @command = coder['command']
42
+ if $subtle
43
+ @tags = coder['tags'] || []
44
+ @views = coder['views'] || []
45
+ @app = coder['app'] || ""
46
+ @modes = coder['modes'] || ""
47
+ end
48
+ end
49
+
50
+ def command
51
+ @command
52
+ end
53
+
54
+ def set_command command
55
+ unless command.nil? || command.empty?
56
+ if @@RE_URI.match command
57
+ split = Regexp.last_match(0).split(/\s+/)
58
+ command = split[split.length - 1]
59
+ command.prepend("http://") unless @@RE_PROTO.match command
60
+ command = URI.parse command
61
+ elsif @@RE_SEARCH.match command
62
+ command = web_search Regexp.last_match(1)
63
+ elsif $subtle
64
+ if @@RE_METHOD.match(command)
65
+ command = Regexp.last_match(0).to_sym
66
+ elsif @@RE_COMMAND.match command
67
+ @tags = []
68
+ @views = []
69
+ @app = ""
70
+ @modes = ""
71
+
72
+ command.split.each do |arg|
73
+ case arg[0]
74
+ when '#' then @tags << arg[1..-1]
75
+ when '@' then @views << arg[1..-1]
76
+ when '+', '^', '*'
77
+ @modes += @@RE_MODES.match(arg).to_s
78
+ else
79
+ if @app.nil? || @app.empty?
80
+ @app = arg
81
+ else
82
+ @app += ' ' + arg
83
+ end
84
+ end
85
+ end
86
+ if @views.any? and not @app.empty? and @tags.empty?
87
+ @tags << "tag_#{rand(1337)}"
88
+ end
89
+ else
90
+ @app = command
91
+ end
92
+ end
93
+ end
94
+ @command = command
95
+ end
96
+
97
+ def web_search search_string, engine = :google
98
+ escaped_string = URI.escape search_string
99
+ case engine
100
+ when :duckduckgo then escaped_string.prepend "https://duckduckgo.com/?q="
101
+ else escaped_string.prepend "https://www.google.com/#q="
102
+ end
103
+ URI.parse escaped_string
104
+ end
105
+
106
+ def find_browser
107
+ begin
108
+ if @browser.nil?
109
+ Subtlext::Client.all.each do |c|
110
+ if c.klass.match(@@RE_BROWSER)
111
+ @browser = c
112
+ @view = c.views.first
113
+ return
114
+ end
115
+ end
116
+ end
117
+ rescue
118
+ @browser = nil
119
+ @view = nil
120
+ end
121
+ end
122
+
123
+ def execute
124
+ case @command
125
+ when String
126
+ if $subtle
127
+ subtle_execute
128
+ else
129
+ system "#{@command} &>/dev/null"
130
+ end
131
+ when URI
132
+ puts @command.to_s
133
+ system "xdg-open '%s' &>/dev/null &" % [ @command.to_s ]
134
+ if $subtle
135
+ find_browser
136
+ @browser.focus unless @browser.nil?
137
+ end
138
+ end
139
+ true
140
+ end
141
+
142
+ def subtle_execute
143
+ tags = @tags.map do |t|
144
+ tag = Subtlext::Tag.first(t) || Subtlext::Tag.new(t)
145
+ tag.save
146
+ tag
147
+ end
148
+ @views.each do |v|
149
+ view = Subtlext::View.first(v) || Subtlext::View.new(v)
150
+ view.save
151
+ view.tag(tags) unless view.nil? or tags.empty?
152
+ end
153
+ unless (client = Subtlext::Client.spawn(@app)).nil?
154
+ client.tags = tags unless tags.empty?
155
+ unless @modes.empty?
156
+ flags = []
157
+
158
+ @modes.each_char do |c|
159
+ case c
160
+ when '+' then flags << :full
161
+ when '^' then flags << :float
162
+ when '*' then flags << :stick
163
+ when '=' then flags << :zaphod
164
+ end
165
+ end
166
+ client.flags = flags
167
+ end
168
+ end
169
+ end
170
+
171
+ def to_s
172
+ "#{@name} => #{command}"
173
+ end
174
+ end
data/lib/dynamic.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Dynamic
2
+
3
+ end
data/lib/editor.rb ADDED
@@ -0,0 +1,251 @@
1
+ require 'menu'
2
+ require 'dynamic'
3
+
4
+ class Editor < Menu
5
+
6
+ include Dynamic
7
+
8
+ @@name = "Edit menu"
9
+
10
+ def self.name
11
+ @@name
12
+ end
13
+
14
+ def name
15
+ "> #{@@name}"
16
+ end
17
+
18
+ def initialize parent
19
+ @parent = parent
20
+ set_style parent.style
21
+ end
22
+
23
+ def to_s
24
+ "Edit menu"
25
+ end
26
+
27
+ def execute
28
+ entries = []
29
+ selection = nil
30
+ while selection != "" && (entries.index selection) != entries.length - 1
31
+ entries = ["Name (#{@parent.name})"]
32
+ entries << "Style"
33
+ entries << "Entries"
34
+ entries << "Run menu"
35
+ entries << "Done"
36
+ selection = show_menu entries, @@name
37
+ case entries.index selection
38
+ when 0 then @parent.set_name show_menu([@parent.name], "Edit Name")
39
+ when 1 then @parent.set_style show_style_menu
40
+ when 2 then show_entries_menu
41
+ when 3 then show_run_menu_menu
42
+ end
43
+ end
44
+ @parent.execute
45
+ end
46
+
47
+ def show_run_menu_menu
48
+ entries = []
49
+ selection = nil
50
+ while selection != "" && (entries.index selection) != entries.length - 1
51
+ if @parent.run_menu?
52
+ entries = ["Disable run menu"]
53
+ else
54
+ entries = ["Enable run menu"]
55
+ end
56
+ entries << "History"
57
+ entries << "Done"
58
+ selection = show_menu entries, "Run menu"
59
+ case entries.index selection
60
+ when 0 then @parent.set_run_menu !@parent.run_menu?
61
+ when 1 then show_history_menu
62
+ end
63
+ end
64
+ end
65
+
66
+ def show_history_menu
67
+ entries = []
68
+ selection = nil
69
+ clear = false
70
+ while selection != "" && (entries.index selection) != entries.length - 1
71
+ entries = ["History length (#{@parent.history.length})"]
72
+ entries << "Items shown in run menu (#{@parent.history.show_num_items})"
73
+ if clear
74
+ entries << "Undo"
75
+ else
76
+ entries << "Clear history"
77
+ end
78
+ entries << "Done"
79
+
80
+ selection = show_menu entries, "History"
81
+ case entries.index.selection
82
+ when 0
83
+ selection = (show_menu [], "Enter a number")
84
+ number = selection.to_i
85
+ @parent.history.set_length number unless number < 1 || number.to_s != selection
86
+ when 1
87
+ selection = (show_menu [], "Enter a number")
88
+ number = (show_menu [], "Enter a number").to_i
89
+ @parent.history.set_show_num_items number unless number.to_s != selection
90
+ when 2 then clear = !clear
91
+ when (entries.length - 1) then @parent.history.clear if clear
92
+ end
93
+ end
94
+ end
95
+
96
+ def show_style_menu
97
+ style = @parent.style
98
+ entries = []
99
+ selection = nil
100
+ while selection != "" && (entries.index selection) != entries.length - 1
101
+ entries = ["Background: (#{style.color :bg})"]
102
+ entries << "Foreground: (#{style.color :fg})"
103
+ entries << "Selected Background: (#{style.color :bg_hi})"
104
+ entries << "Selected Foreground: (#{style.color :fg_hi})"
105
+ if style.font.nil?
106
+ entries << "Font: (default)"
107
+ else
108
+ entries << "Font: (#{style.font})"
109
+ end
110
+ entries << "Done"
111
+ selection = show_menu entries, "Edit style"
112
+ colors = [:bg, :fg, :bg_hi, :fg_hi]
113
+ unless (entries.index selection).nil?
114
+ if (entries.index selection) < 4
115
+ style.set_color colors[entries.index selection], show_menu([style.color(colors[entries.index selection])], "Enter a color")
116
+ elsif (entries.index selection) < 5
117
+ if style.font.nil?
118
+ selection = show_menu(["default"], "Set font")
119
+ else
120
+ selection = show_menu([style.font], "Set font")
121
+ end
122
+ unless selection.nil? || selection == "default"
123
+ style.set_font selection
124
+ end
125
+ end
126
+ end
127
+ end
128
+ style
129
+ end
130
+
131
+ def show_menu entries, name, show_edit_menue = false
132
+ super
133
+ end
134
+
135
+ def show_entries_menu
136
+ entries = ["Edit/Remove entries"]
137
+ entries << "Add entries"
138
+ entries << "Done"
139
+ selection = nil
140
+ while selection != "" && (entries.index selection) != 2
141
+ selection = show_menu entries, "Edit entries"
142
+ case entries.index selection
143
+ when 0 then show_edit_menu
144
+ when 1 then show_add_menu
145
+ end
146
+ end
147
+ end
148
+
149
+ def show_edit_menu
150
+ selection = nil
151
+ while selection != "" && @parent.items[selection].nil?
152
+ selection = show_menu @parent.items.keys.sort, "Select item to edit"
153
+ item = @parent.items[selection]
154
+ unless item.nil?
155
+ if item.is_a? Command
156
+ show_edit_cmd_menu item
157
+ else
158
+ show_edit_menu_menu item
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ def show_add_menu
165
+ entries = []
166
+ entries = ["Command"]
167
+ entries << "Menu"
168
+ entries << "Done"
169
+ selection = nil
170
+ while selection != "" && (entries.index selection) != entries.length - 1
171
+ selection = show_menu entries, "Add items"
172
+ case entries.index selection
173
+ when 0 then show_edit_cmd_menu
174
+ when 1 then show_edit_menu_menu
175
+ end
176
+ end
177
+ end
178
+
179
+ def show_edit_cmd_menu command = Command.new("New command", "")
180
+ new = false
181
+ if (@parent.remove_item command).nil?
182
+ new = true
183
+ end
184
+ entries = []
185
+ selection = nil
186
+ delete = false
187
+ while selection != "" && (entries.index selection) != entries.length - 1
188
+ entries = ["Name (#{command.name})"]
189
+ entries << "Command (#{command.command})"
190
+ if new
191
+ string = "Add command"
192
+ else
193
+ string = "Edit command"
194
+ if delete
195
+ entries << "Undo"
196
+ else
197
+ entries << "Delete"
198
+ end
199
+ end
200
+ entries << "Done"
201
+ selection = show_menu entries, "Add Command"
202
+ case entries.index selection
203
+ when 0
204
+ new_name = show_menu([command.name], "Enter a name")
205
+ command.set_name new_name unless new_name.empty?
206
+ when 1
207
+ history = History.new 1, 1
208
+ history.update command.command unless command.command.nil? or command.command.empty?
209
+ new_command = Run_Menu.new(self, history, "Enter a command").show_menu
210
+ command.set_command new_command unless new_command.empty?
211
+ when 2 then delete = !delete unless new
212
+ end
213
+ end
214
+ delete = true if selection == "" && new
215
+ @parent.set_item command unless delete
216
+ end
217
+
218
+ def show_edit_menu_menu menu = nil
219
+ new = menu.nil?
220
+ if new
221
+ menu = Menu.new "New menu"
222
+ menu.set_style @parent.style
223
+ end
224
+ @parent.remove_item menu
225
+ entries = []
226
+ selection = nil
227
+ delete = false
228
+ while selection != "" && (entries.index selection) != entries.length - 1
229
+ entries = ["Name (#{menu.name})"]
230
+ if new
231
+ string = "Add menu"
232
+ else
233
+ string = "Edit menu"
234
+ if delete
235
+ entries << "Undo"
236
+ else
237
+ entries << "Remove"
238
+ end
239
+ end
240
+ entries << "Done"
241
+ selection = show_menu entries, string
242
+ if (entries.index selection) == 0
243
+ new_name = show_menu [], "Enter a name"
244
+ menu.set_name new_name unless new_name.empty?
245
+ end
246
+ delete = !delete if (entries.index selection) == 1 && !new
247
+ end
248
+ delete = true if selection == "" && new
249
+ @parent.set_item menu unless delete
250
+ end
251
+ end
data/lib/history.rb ADDED
@@ -0,0 +1,43 @@
1
+ class History
2
+ def initialize length, show_num_items = 5
3
+ @items = {}
4
+ set_length length
5
+ set_show_num_items show_num_items
6
+ end
7
+
8
+ def length
9
+ @length
10
+ end
11
+
12
+ def show_num_items
13
+ @show_num_items
14
+ end
15
+
16
+ def set_length length
17
+ @length = length
18
+ end
19
+
20
+ def set_show_num_items num
21
+ @show_num_items = num
22
+ end
23
+
24
+ def update item
25
+ @items.each {|itm,age| @items[itm] += 1}
26
+ @items[item] = 0
27
+ if @items.length > @length
28
+ @items.delete((@items.max_by {|itm, age| age}).first)
29
+ end
30
+ end
31
+
32
+ def items
33
+ ret = {
34
+ :first => ((@items.sort_by {|item,age| age}).map {|pair| pair.first}).first(@show_num_items)
35
+ }
36
+ ret.store :rest, (@items.reject {|item, age| ret[:first].include? item}).keys
37
+ ret
38
+ end
39
+
40
+ def clear
41
+ @items = {}
42
+ end
43
+ end
data/lib/item.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Item
2
+ def name
3
+ @name
4
+ end
5
+
6
+ def set_name name
7
+ @name = name
8
+ end
9
+ end
data/lib/menu.rb ADDED
@@ -0,0 +1,93 @@
1
+ require 'item'
2
+
3
+ class Menu
4
+
5
+ include Item
6
+
7
+ def initialize name
8
+ @name = name
9
+ @items = Hash.new
10
+ @style = Style.new
11
+ set_item Editor.new self
12
+ end
13
+
14
+ def encode_with coder
15
+ coder['name'] = @name
16
+ coder['items'] = items
17
+ coder['style'] = @style
18
+ end
19
+
20
+ def init_with coder
21
+ @name = coder['name']
22
+ @items = coder['items']
23
+ @style = coder['style']
24
+ set_item Editor.new self
25
+ end
26
+
27
+ def set_item item
28
+ @items[item.name] = item unless @items[item.name].is_a? Dynamic
29
+ end
30
+
31
+ def items
32
+ @items.reject { |name,item| item.is_a?(Dynamic) }
33
+ end
34
+
35
+ def remove_item item
36
+ @items.delete item.name unless item.is_a? Dynamic
37
+ end
38
+
39
+ def name
40
+ "> #{super}"
41
+ end
42
+
43
+ def style
44
+ @style
45
+ end
46
+
47
+ def set_style style
48
+ @style = style
49
+ end
50
+
51
+ def to_s
52
+ string = "#{name}\n"
53
+ string += (@items.keys.sort.map {|name| name.prepend(" ")}).join("\n")
54
+ end
55
+
56
+ def execute
57
+ show = true
58
+ while show
59
+ selection = show_menu @items.keys.sort, @name
60
+ item = @items[selection]
61
+ if item.nil?
62
+ show = false
63
+ else
64
+ show = !item.execute unless item.nil?
65
+ end
66
+ end
67
+ !item.nil?
68
+ end
69
+ def filter_entries entries
70
+ if @items.nil?
71
+ entries
72
+ else
73
+ entries.reject {|entry| @items[entry].is_a?(Editor)}
74
+ end
75
+ end
76
+ def show_menu entries, name, show_edit_menu = true
77
+ entries = filter_entries entries
78
+ unless $read_only || self.is_a?(Dynamic)
79
+ entries << "> #{Editor.name}"
80
+ end
81
+ command = "echo \"#{entries.join "\n"}\" | dmenu -i -b -l #{$lines} #{get_font_string} -nf \"#{@style.color :fg}\" -nb \"#{@style.color :bg}\" -sf \"#{@style.color :fg_hi}\" -sb \"#{@style.color :bg_hi}\" -p \"#{name}\""
82
+ (`#{command}`).strip
83
+ end
84
+
85
+ def get_font_string
86
+ font = ""
87
+ unless @style.font.nil?
88
+ font = "-fn \"#{@style.font}\""
89
+ end
90
+ font
91
+ end
92
+
93
+ end
data/lib/root_menu.rb ADDED
@@ -0,0 +1,40 @@
1
+ require 'menu'
2
+ class Root_Menu < Menu
3
+
4
+ def initialize history_length = 1000, history_items = 5
5
+ super "Dynmenu"
6
+ @run_menu = true
7
+ @history = History.new history_length, history_items
8
+ set_item Run_Menu.new self, @history
9
+ end
10
+
11
+ def run_menu?
12
+ @run_menu
13
+ end
14
+
15
+ def filter_entries entries
16
+ partitions = super.partition {|entry| @items[entry].is_a?(Run_Menu)}
17
+ if run_menu?
18
+ partitions[0] + partitions[1]
19
+ else
20
+ partitions[1]
21
+ end
22
+ end
23
+
24
+ def set_run_menu value
25
+ @run_menu = value
26
+ end
27
+
28
+ def encode_with coder
29
+ super
30
+ coder['run_menu'] = @run_menu
31
+ coder['history'] = @history
32
+ end
33
+
34
+ def init_with coder
35
+ super
36
+ @run_menu = coder['run_menu']
37
+ @history = coder['history']
38
+ set_item Run_Menu.new self, @history if @run_menu
39
+ end
40
+ end
data/lib/run_menu.rb ADDED
@@ -0,0 +1,50 @@
1
+ require 'menu'
2
+ require 'dynamic'
3
+ class Run_Menu < Menu
4
+
5
+ include Dynamic
6
+
7
+ @@RE_HIDDEN = Regexp.new /\/{,1}\.[^\/]*$/
8
+ def initialize parent, history = History.new(1, 5), name = "Run"
9
+ @name = name
10
+ @parent = parent
11
+ @history = history
12
+ set_style parent.style
13
+ end
14
+
15
+ def name
16
+ ">#{super}"
17
+ end
18
+
19
+ def execute
20
+ command = show_menu
21
+ Command.new("", command).execute
22
+ @history.update command unless command.empty?
23
+ !command.empty?
24
+ end
25
+
26
+ def show_menu
27
+ get_files
28
+ history_items = @history.items
29
+ items = history_items[:first] + @files + history_items[:rest]
30
+ super items, @name
31
+ end
32
+
33
+ def get_files dirs = (`echo $PATH`).split(':')
34
+ @files = []
35
+ dirs.each do |dir|
36
+ get_files_rec dir
37
+ end
38
+ end
39
+ def get_files_rec file
40
+ return if file.match @@RE_HIDDEN
41
+ if File.directory? file
42
+ Dir.foreach file do |cur_file|
43
+ get_files_rec cur_file
44
+ end
45
+ else
46
+ @files << file
47
+ end
48
+ end
49
+
50
+ end
data/lib/style.rb ADDED
@@ -0,0 +1,41 @@
1
+ class Style
2
+ @@re_color = Regexp.new(/^#[0-9a-fA-F]{6}$/)
3
+ def initialize
4
+ @colors = {
5
+ :bg => "#202020",
6
+ :fg => "#757575",
7
+ :bg_hi => "#303030",
8
+ :fg_hi => "#FECF35"
9
+ }
10
+ end
11
+
12
+ def set_color color, value
13
+ unless @colors.keys.include? color
14
+ raise ArgumentError, "Invalid key!"
15
+ end
16
+ unless @@re_color.match value
17
+ raise ArgumentError, "Invalid color string!"
18
+ end
19
+ @colors[color] = value
20
+ end
21
+
22
+ def color color
23
+ unless @colors.keys.include? color
24
+ raise ArgumentError, "Invalid key!"
25
+ end
26
+ @colors[color]
27
+ end
28
+
29
+ def set_font font
30
+ @font = font
31
+ end
32
+ def to_s
33
+ string = ""
34
+ string = @font unless @font.nil?
35
+ string += " #{@colors}"
36
+ end
37
+
38
+ def font
39
+ @font
40
+ end
41
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dynmenu
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joakim Reinert
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-03 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A dmenu wrapper for subtle wm
15
+ email: mail@jreinert.com
16
+ executables:
17
+ - dynmenu
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/item.rb
22
+ - lib/editor.rb
23
+ - lib/style.rb
24
+ - lib/menu.rb
25
+ - lib/root_menu.rb
26
+ - lib/run_menu.rb
27
+ - lib/history.rb
28
+ - lib/dynamic.rb
29
+ - lib/command.rb
30
+ - bin/dynmenu
31
+ homepage: https://github.com/supasnashbuhl/dynmenu
32
+ licenses: []
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 1.8.23
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: Dynmenu
55
+ test_files: []