fluxbox_apps_menu 1.2.0 → 1.3.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 +4 -4
- data/Gemfile.lock +6 -3
- data/README.md +12 -10
- data/lib/fluxbox_apps_menu.rb +23 -14
- data/lib/fluxbox_apps_menu.yaml +5 -0
- data/lib/fluxbox_apps_menu/cli.rb +18 -12
- data/lib/fluxbox_apps_menu/config.rb +3 -2
- data/lib/fluxbox_apps_menu/desktop_file.rb +5 -3
- data/lib/fluxbox_apps_menu/menu.rb +82 -28
- data/lib/fluxbox_apps_menu/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 299c16c1c64506b78ab3c7d9cdf87f0c7b035315
|
4
|
+
data.tar.gz: a5ed2130437276cdc9329db41b91725ff3a260ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5268a846daa828e7f7bff6751f42cbb1ba46e00a9e24cfa960d5f88b2728e2093b1e87a42c847509aee474eb728ece1de165973fab0fe6f33450cefe01930cf2
|
7
|
+
data.tar.gz: b3954afe8f8967aba09b1f265551c3c21c680a4ab99808d010b6e22eb2406c5e1886ae18a4bda75bb69e2f97bf33e16b3f8d6fd891d6b2893e0eb837015e424c
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fluxbox_apps_menu (1.
|
4
|
+
fluxbox_apps_menu (1.3.0)
|
5
5
|
inifile (~> 3.0)
|
6
6
|
thor
|
7
7
|
|
@@ -9,8 +9,8 @@ GEM
|
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
11
|
inifile (3.0.0)
|
12
|
-
rake (
|
13
|
-
thor (0.19.
|
12
|
+
rake (12.0.0)
|
13
|
+
thor (0.19.4)
|
14
14
|
|
15
15
|
PLATFORMS
|
16
16
|
ruby
|
@@ -19,3 +19,6 @@ DEPENDENCIES
|
|
19
19
|
bundler (~> 1.6)
|
20
20
|
fluxbox_apps_menu!
|
21
21
|
rake
|
22
|
+
|
23
|
+
BUNDLED WITH
|
24
|
+
1.14.5
|
data/README.md
CHANGED
@@ -24,21 +24,23 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
## Usage
|
26
26
|
|
27
|
-
Build the menu
|
27
|
+
Build the menu:
|
28
28
|
|
29
29
|
$ fluxbox_apps_menu build
|
30
|
-
|
31
|
-
Create a copy of the config file (*fluxbox_apps_menu.yaml*) under
|
32
|
-
the _~/.fluxbox_ folder
|
33
30
|
|
34
|
-
|
35
|
-
|
36
|
-
When the application menu is built it can be included in
|
37
|
-
your main fluxbox menu file (usually *~/.fluxbox/menu*) adding
|
38
|
-
the row below where you want display it:
|
31
|
+
When the application menu is built it can be included in your main fluxbox menu file
|
32
|
+
(usually *~/.fluxbox/menu*) adding the row below where you want display it:
|
39
33
|
|
40
34
|
[include] (~/.fluxbox/menu-apps)
|
41
35
|
|
36
|
+
|
37
|
+
To start with customizations create a copy of the config file (*fluxbox_apps_menu.yaml*)
|
38
|
+
under the _~/.fluxbox_ folder:
|
39
|
+
|
40
|
+
$ fluxbox_apps_menu config
|
41
|
+
|
42
|
+
Once completed build again!
|
43
|
+
|
42
44
|
## Get help
|
43
45
|
|
44
46
|
Where to start
|
@@ -48,7 +50,7 @@ Where to start
|
|
48
50
|
Get help for a specific task
|
49
51
|
|
50
52
|
$ fluxbox_apps_menu help build
|
51
|
-
$ fluxbox_apps_menu help
|
53
|
+
$ fluxbox_apps_menu help config
|
52
54
|
|
53
55
|
More help
|
54
56
|
|
data/lib/fluxbox_apps_menu.rb
CHANGED
@@ -4,16 +4,13 @@ require 'fluxbox_apps_menu/menu'
|
|
4
4
|
require 'fluxbox_apps_menu/desktop_file'
|
5
5
|
require 'fluxbox_apps_menu/utils'
|
6
6
|
|
7
|
-
$VERBOSE = nil
|
8
|
-
|
9
7
|
module FluxboxAppsMenu
|
10
8
|
|
11
9
|
class Builder
|
12
10
|
|
13
11
|
def initialize(opts)
|
14
|
-
#p opts; exit
|
15
12
|
@filename = opts[:filename].to_s.empty? ? 'menu-apps' : opts[:filename]
|
16
|
-
@
|
13
|
+
@verbose = opts[:verbose]
|
17
14
|
@overwrite = opts[:overwrite]
|
18
15
|
@cfg = FluxboxAppsMenu::Config.new
|
19
16
|
@fmenu = FluxboxAppsMenu::Menu.new(@cfg)
|
@@ -22,7 +19,7 @@ module FluxboxAppsMenu
|
|
22
19
|
def create_menu
|
23
20
|
if @overwrite == false
|
24
21
|
if File.exists?(File.expand_path("~/.fluxbox/#{@filename}"))
|
25
|
-
puts "The file #{@filename} already exists!"
|
22
|
+
STDERR.puts 'Fatal Error! '.bold.red "The file #{@filename} already exists!"
|
26
23
|
exit
|
27
24
|
end
|
28
25
|
end
|
@@ -35,7 +32,7 @@ module FluxboxAppsMenu
|
|
35
32
|
def init_config
|
36
33
|
unless @overwrite
|
37
34
|
if File.exists?(File.expand_path("~/.fluxbox/fluxbox_apps_menu.yaml"))
|
38
|
-
puts '
|
35
|
+
STDERR.puts 'Fatal Error! '.bold.red + "The file 'fluxbox_apps_menu.yaml' already exists in '#{File.expand_path('~/.fluxbox')}'"
|
39
36
|
exit
|
40
37
|
end
|
41
38
|
end
|
@@ -47,7 +44,7 @@ module FluxboxAppsMenu
|
|
47
44
|
def scan_app_folder
|
48
45
|
@cfg.app_paths.each do |d|
|
49
46
|
|
50
|
-
Dir.glob(d + '/*.desktop') do |f|
|
47
|
+
Dir.glob(File.expand_path(d + '/*.desktop')) do |f|
|
51
48
|
|
52
49
|
ini = DesktopFile.new(f, @cfg)
|
53
50
|
|
@@ -56,35 +53,47 @@ module FluxboxAppsMenu
|
|
56
53
|
name = ini.name
|
57
54
|
|
58
55
|
if ini.hidden?
|
59
|
-
puts '[
|
56
|
+
puts '[H] '.bold.gray + "\"#{name}\" (#{f})" if @verbose
|
60
57
|
next
|
61
58
|
end
|
62
59
|
|
63
60
|
cat = ini.categories
|
64
61
|
if cat.nil?
|
65
|
-
puts '[
|
62
|
+
puts '[C] '.bold.red + "\"#{name}\" (#{f})" if @verbose
|
66
63
|
next
|
67
64
|
end
|
68
65
|
|
69
66
|
begin
|
70
|
-
submenu = @fmenu.assign_menu(cat, name)
|
67
|
+
submenu = @fmenu.assign_menu(cat, name)
|
71
68
|
rescue NoCategoriesError => e
|
72
|
-
puts '
|
69
|
+
STDERR.puts 'Fatal Error! '.bold.red + "The \"#{e.message}\" menu item doesn't have any category, fix it to your \"fluxbox_menu_apps.yaml\""
|
73
70
|
exit
|
74
71
|
end
|
75
72
|
|
76
73
|
unless submenu.nil?
|
77
74
|
icon = ini.icon
|
78
75
|
if icon.nil?
|
79
|
-
puts '[
|
76
|
+
puts '[I] '.bold.yellow + "\"#{name}\" (#{f})" if @verbose
|
80
77
|
end
|
81
78
|
|
82
|
-
submenu[name] =
|
79
|
+
submenu[name] = MenuItem.new(:label => name, :icon => icon, :command => ini.exec)
|
80
|
+
puts '[V]'.bold.green + " \"#{name}\" (#{f})" if @verbose
|
83
81
|
else
|
84
|
-
puts '
|
82
|
+
STDERR.puts 'Warning! '.bold.yellow + "\"#{name}\" doesn't have any mapped category among: #{ini.categories.join(', ')}, fix it to your \"fluxbox_menu_apps.yaml\" "
|
85
83
|
end
|
86
84
|
end
|
87
85
|
end
|
86
|
+
|
87
|
+
if @verbose
|
88
|
+
puts ''
|
89
|
+
puts 'Quick Help:'
|
90
|
+
puts ''
|
91
|
+
puts ' [V]: Everything is ok'.bold.green
|
92
|
+
puts ' [H]: Hidden app'.bold.gray
|
93
|
+
puts ' [I]: App without icon'.bold.yellow
|
94
|
+
puts ' [C]: App without categories'.bold.red
|
95
|
+
puts ''
|
96
|
+
end
|
88
97
|
end
|
89
98
|
|
90
99
|
end
|
data/lib/fluxbox_apps_menu.yaml
CHANGED
@@ -7,6 +7,10 @@
|
|
7
7
|
:banned_files:
|
8
8
|
- 'qmmp_.*'
|
9
9
|
- 'umplayer_.*'
|
10
|
+
:unhide_files:
|
11
|
+
- 'nm-connection-editor'
|
12
|
+
- 'bluedevilsendfile'
|
13
|
+
- 'bluedevilwizard'
|
10
14
|
:icon_paths:
|
11
15
|
- /usr/share/icons/gnome/16x16/apps
|
12
16
|
- /usr/share/icons/oxygen/16x16/apps
|
@@ -22,6 +26,7 @@
|
|
22
26
|
- /usr/share/applications
|
23
27
|
- /usr/share/applications/kde4
|
24
28
|
- /usr/share/applications/YaST2
|
29
|
+
- ~/.local/share/applications
|
25
30
|
:menu:
|
26
31
|
Development:
|
27
32
|
:icon: applications-development
|
@@ -8,33 +8,39 @@ module FluxboxAppsMenu
|
|
8
8
|
|
9
9
|
desc 'build', 'Build the menu'
|
10
10
|
method_option :filename, :aliases => '-f', :default => '', :desc => 'Save as filename.'
|
11
|
-
method_option :
|
11
|
+
method_option :verbose, :aliases => '-v', :default => false, :type => :boolean, :desc => 'Print helping output messages.'
|
12
12
|
method_option :overwrite, :aliases => '-o', :default => true, :type => :boolean, :desc => 'Overwrite the app menu if exists.'
|
13
13
|
def build
|
14
14
|
FluxboxAppsMenu::Builder.new(options).create_menu
|
15
15
|
end
|
16
16
|
|
17
|
-
desc '
|
17
|
+
desc 'config', 'Make a local copy of the configuration file.'
|
18
18
|
method_option :overwrite, :aliases => '-o', :default => false, :type => :boolean, :desc => 'Overwrite the config file if exists.'
|
19
|
-
def
|
19
|
+
def config
|
20
20
|
FluxboxAppsMenu::Builder.new(options).init_config
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def help(arg = nil)
|
24
24
|
if arg.nil?
|
25
25
|
puts <<EOL
|
26
|
+
|
26
27
|
FluxboxAppsMenu v.#{FluxboxAppsMenu::VERSION} by Fabio Mucciante
|
27
28
|
|
28
29
|
Description:
|
29
|
-
|
30
|
-
|
30
|
+
Generates a menu for Fluxbox containing the applications installed
|
31
|
+
and visible in other DE menus.
|
32
|
+
|
33
|
+
Customizations on the building process are achieved editing the
|
34
|
+
"fluxbox_apps_menu.yaml" file copied under the "~/.fluxbox"
|
35
|
+
folder by the "config" task.
|
36
|
+
Watch the online page for more info:
|
37
|
+
|
38
|
+
https://github.com/fabiomux/fluxbox_apps_menu/wiki
|
31
39
|
|
32
|
-
|
33
|
-
|
40
|
+
The file containing the application tree will be created by
|
41
|
+
default to "~/.fluxbox/menu-apps" and can be included within the
|
42
|
+
main menu adding the line:
|
34
43
|
|
35
|
-
The application's menu file will be created in "~/.fluxbox/menu-apps"
|
36
|
-
and can be included within your fluxbox menu adding the row below:
|
37
|
-
|
38
44
|
[include] (~/.fluxbox/menu-apps)
|
39
45
|
|
40
46
|
EOL
|
@@ -44,7 +50,7 @@ EOL
|
|
44
50
|
end
|
45
51
|
end
|
46
52
|
|
47
|
-
|
53
|
+
# default_task :build
|
48
54
|
end
|
49
55
|
|
50
56
|
end
|
@@ -2,7 +2,7 @@ require 'yaml'
|
|
2
2
|
|
3
3
|
module FluxboxAppsMenu
|
4
4
|
class Config
|
5
|
-
attr_reader :lang, :icon_paths, :filename, :banned_files, :app_paths, :icons, :terminal
|
5
|
+
attr_reader :lang, :icon_paths, :filename, :banned_files, :unhide_files, :app_paths, :icons, :terminal
|
6
6
|
attr_accessor :menu
|
7
7
|
|
8
8
|
def initialize
|
@@ -19,8 +19,9 @@ module FluxboxAppsMenu
|
|
19
19
|
yaml = YAML.load_file(@filename)
|
20
20
|
|
21
21
|
@banned_files = yaml[:banned_files]
|
22
|
+
@unhide_files = yaml[:unhide_files]
|
22
23
|
@icon_paths = yaml[:icon_paths]
|
23
|
-
@app_paths = yaml[:app_paths]
|
24
|
+
@app_paths = yaml[:app_paths]
|
24
25
|
@menu = yaml[:menu]
|
25
26
|
@icons = yaml[:icons]
|
26
27
|
@terminal = yaml[:terminal]
|
@@ -22,6 +22,7 @@ module FluxboxAppsMenu
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def hidden?
|
25
|
+
@cfg.unhide_files.each { |r| return false if @filename =~ Regexp.new(r) }
|
25
26
|
%w(true 1).include? @ini['Desktop Entry']['NoDisplay'].to_s
|
26
27
|
end
|
27
28
|
|
@@ -44,9 +45,10 @@ module FluxboxAppsMenu
|
|
44
45
|
end
|
45
46
|
|
46
47
|
def exec
|
47
|
-
com = @ini['Desktop Entry']['Exec'].to_s
|
48
|
-
.gsub(
|
49
|
-
.gsub(
|
48
|
+
com = @ini['Desktop Entry']['Exec'].to_s
|
49
|
+
.gsub(/((?:"){,1})%c\1/, "\\1#{name}\\1")
|
50
|
+
.gsub(/((?:"){,1})(%F|%i|%U|%f|%m|%u)\1/, '')
|
51
|
+
.gsub(/[ ]{2,}/, ' ').gsub(/\ }/, '}').strip
|
50
52
|
|
51
53
|
terminal? ? @cfg.terminal + ' ' + com : com
|
52
54
|
end
|
@@ -1,43 +1,92 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
1
3
|
module FluxboxAppsMenu
|
2
4
|
|
3
|
-
class
|
5
|
+
class MenuItem
|
6
|
+
attr_accessor :label, :icon, :command, :level
|
4
7
|
|
5
|
-
def initialize(
|
6
|
-
@
|
7
|
-
|
8
|
+
def initialize(args = {})
|
9
|
+
@label = args[:label] if args.has_key? :label
|
10
|
+
@icon = args[:icon] if args.has_key? :icon
|
11
|
+
@command = args[:command] if args.has_key? :command
|
12
|
+
@level = args[:level] if args.has_key? :level
|
8
13
|
|
9
|
-
|
10
|
-
|
14
|
+
@rendered = []
|
15
|
+
@level ||= 0
|
11
16
|
end
|
12
17
|
|
13
|
-
def
|
14
|
-
|
18
|
+
def wrap_item(str)
|
19
|
+
"#{' ' * level}#{str}\n"
|
15
20
|
end
|
16
21
|
|
17
|
-
def
|
18
|
-
|
22
|
+
def <<(str)
|
23
|
+
@rendered << str
|
24
|
+
self
|
19
25
|
end
|
20
26
|
|
21
|
-
def
|
22
|
-
|
27
|
+
def render
|
28
|
+
@rendered
|
23
29
|
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class SeparatorItem < SimpleDelegator
|
24
33
|
|
25
|
-
def
|
26
|
-
|
34
|
+
def initialize(obj)
|
35
|
+
super(obj)
|
36
|
+
obj << wrap_item('[separator]')
|
27
37
|
end
|
38
|
+
end
|
28
39
|
|
29
|
-
|
30
|
-
private
|
40
|
+
class ExecItem < SimpleDelegator
|
31
41
|
|
32
|
-
def
|
42
|
+
def initialize(obj)
|
43
|
+
super(obj)
|
33
44
|
str = []
|
34
|
-
str <<
|
45
|
+
str << '[exec]'
|
35
46
|
str << "(#{label.gsub(/(?<!\\)\)/, '\)')})" unless label.to_s.empty?
|
36
47
|
str << "{#{command}}" unless command.nil?
|
37
48
|
str << "<#{icon}>" unless icon.to_s.empty?
|
38
49
|
|
39
|
-
str.join(' ')
|
50
|
+
obj << wrap_item(str.join(' '))
|
40
51
|
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class StartSubmenuItem < SimpleDelegator
|
55
|
+
|
56
|
+
def initialize(obj)
|
57
|
+
super(obj)
|
58
|
+
str = []
|
59
|
+
str << '[submenu]'
|
60
|
+
str << "(#{label.gsub(/(?<!\\)\)/, '\)')})" unless label.to_s.empty?
|
61
|
+
str << "<#{icon}>" unless icon.to_s.empty?
|
62
|
+
|
63
|
+
obj << wrap_item(str.join(' '))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class EndSubmenuItem < SimpleDelegator
|
68
|
+
|
69
|
+
def initialize(obj)
|
70
|
+
super(obj)
|
71
|
+
obj << wrap_item('[end]')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Menu
|
76
|
+
|
77
|
+
def initialize(cfg = nil)
|
78
|
+
@cfg = cfg.nil? ? FluxboxAppsMenu::Config.new : cfg
|
79
|
+
end
|
80
|
+
|
81
|
+
def assign_menu(cat, label)
|
82
|
+
traverse_menu(@cfg.menu, cat.map(&:downcase), label)[0]
|
83
|
+
end
|
84
|
+
|
85
|
+
def render
|
86
|
+
render_menu(@cfg.menu)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
41
90
|
|
42
91
|
def traverse_menu(menu, cat, label, selected_index = nil)
|
43
92
|
#categories with smaller index are the favorites
|
@@ -50,7 +99,7 @@ module FluxboxAppsMenu
|
|
50
99
|
if info.class == Hash
|
51
100
|
subitems = info.select { |k, v| k.class == String }
|
52
101
|
|
53
|
-
# when a label is set the path has high priority
|
102
|
+
# when a label is set the path has high priority
|
54
103
|
return [info, 0] if info.has_key?(label)
|
55
104
|
|
56
105
|
if info.has_key? :mandatory_categories
|
@@ -71,7 +120,7 @@ module FluxboxAppsMenu
|
|
71
120
|
if categories.include?(c.strip)
|
72
121
|
i = categories.index(c)
|
73
122
|
if i < selected_index
|
74
|
-
selected = info
|
123
|
+
selected = info
|
75
124
|
selected_index = i
|
76
125
|
end
|
77
126
|
end
|
@@ -84,23 +133,28 @@ module FluxboxAppsMenu
|
|
84
133
|
end
|
85
134
|
|
86
135
|
def render_menu(menu, level = 0)
|
87
|
-
prefix = ' ' * (level)
|
88
136
|
text = ''
|
89
137
|
|
90
138
|
# sort the items but let menu folders at the top
|
91
|
-
menu = menu.select { |k, v| k.class == String }.sort_by { |k, v| v.
|
139
|
+
menu = menu.select { |k, v| k.class == String }.sort_by { |k, v| (v.kind_of? MenuItem) ? k.downcase : '' }
|
92
140
|
menu.each do |name, items|
|
93
|
-
|
141
|
+
|
142
|
+
if items.class == Hash
|
94
143
|
icon = items[:icon]
|
95
144
|
items = items.select { |k, v| k.class == String }
|
96
145
|
subitems = render_menu(items, level + 1)
|
97
146
|
|
98
147
|
unless subitems.empty?
|
99
|
-
text +=
|
148
|
+
text += begin
|
149
|
+
i = MenuItem.new(:level => level, :label => name, :icon => @cfg.expand_icon(nil, icon))
|
150
|
+
EndSubmenuItem.new(StartSubmenuItem.new(i) << subitems).render
|
151
|
+
end.join
|
100
152
|
end
|
101
|
-
|
102
|
-
|
103
|
-
|
153
|
+
elsif items.kind_of? MenuItem
|
154
|
+
text += begin
|
155
|
+
items.level = level
|
156
|
+
ExecItem.new(items).render
|
157
|
+
end.join
|
104
158
|
end
|
105
159
|
end
|
106
160
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluxbox_apps_menu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fabio Mucciante
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|