dynmenu 0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []