fluxbox_apps_menu 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/Gemfile.lock +21 -0
- data/LICENSE +674 -0
- data/README.md +57 -0
- data/Rakefile +2 -0
- data/bin/fluxbox_apps_menu +6 -0
- data/fluxbox_apps_menu.gemspec +26 -0
- data/lib/fluxbox_apps_menu.rb +85 -0
- data/lib/fluxbox_apps_menu.yaml +123 -0
- data/lib/fluxbox_apps_menu/cli.rb +50 -0
- data/lib/fluxbox_apps_menu/config.rb +50 -0
- data/lib/fluxbox_apps_menu/desktop_file.rb +69 -0
- data/lib/fluxbox_apps_menu/menu.rb +100 -0
- data/lib/fluxbox_apps_menu/utils.rb +21 -0
- data/lib/fluxbox_apps_menu/version.rb +3 -0
- metadata +127 -0
data/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# FluxboxAppsMenu
|
2
|
+
|
3
|
+
FluxboxAppsMenu create an applications menu file for Fluxbox Window Manager
|
4
|
+
including the applications stored within the folders containing the
|
5
|
+
_.desktop_ files and discarding automatically those marked as hidden.
|
6
|
+
|
7
|
+
They will be organized in several categories and sub-categories specified
|
8
|
+
within the config file *fluxbox_apps_menu.yaml*
|
9
|
+
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'fluxbox_apps_menu'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install fluxbox_apps_menu
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
Build the menu
|
28
|
+
|
29
|
+
$ fluxbox_apps_menu build
|
30
|
+
|
31
|
+
Create a copy of the config file (*fluxbox_apps_menu.yaml*) under
|
32
|
+
the _~/.fluxbox_ folder
|
33
|
+
|
34
|
+
$ fluxbox_apps_menu menuconfig
|
35
|
+
|
36
|
+
Get help
|
37
|
+
|
38
|
+
$ fluxbox_apps_menu help
|
39
|
+
|
40
|
+
Get help for a specific task
|
41
|
+
|
42
|
+
$ fluxbox_apps_menu help build
|
43
|
+
$ fluxbox_apps_menu help menuconfig
|
44
|
+
|
45
|
+
When the application's menu is built it can be included in
|
46
|
+
your main fluxbox menu file (usually *~/.fluxbox/menu*) adding
|
47
|
+
the row below where you want display it:
|
48
|
+
|
49
|
+
[include] (~/.fluxbox/menu-apps)
|
50
|
+
|
51
|
+
## Contributing
|
52
|
+
|
53
|
+
1. Fork it ( https://github.com/fabiomux/fluxbox_apps_menu/fork )
|
54
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
55
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
56
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
57
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'fluxbox_apps_menu/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'fluxbox_apps_menu'
|
8
|
+
spec.version = FluxboxAppsMenu::VERSION
|
9
|
+
spec.authors = ['Fabio Mucciante']
|
10
|
+
spec.email = ['fabio.mucciante@gmail.com']
|
11
|
+
spec.summary = %q{Build the Fluxbox apps menu.}
|
12
|
+
spec.description = %q{This script reads the .desktop files installed and build the application's menu under the Fluxbox home folder.}
|
13
|
+
spec.homepage = 'https://github.com/fabiomux/fluxbox_apps_menu'
|
14
|
+
spec.license = 'GPL v.3'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
|
24
|
+
spec.add_runtime_dependency "inifile", "~> 3.0"
|
25
|
+
spec.add_runtime_dependency "thor"
|
26
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'fluxbox_apps_menu/version'
|
2
|
+
require 'fluxbox_apps_menu/config'
|
3
|
+
require 'fluxbox_apps_menu/menu'
|
4
|
+
require 'fluxbox_apps_menu/desktop_file'
|
5
|
+
require 'fluxbox_apps_menu/utils'
|
6
|
+
|
7
|
+
$VERBOSE = nil
|
8
|
+
|
9
|
+
module FluxboxAppsMenu
|
10
|
+
|
11
|
+
class Builder
|
12
|
+
|
13
|
+
def initialize(opts)
|
14
|
+
#p opts; exit
|
15
|
+
@filename = opts[:filename].to_s.empty? ? 'menu-apps' : opts[:filename]
|
16
|
+
@silent = opts[:silent]
|
17
|
+
@overwrite = opts[:overwrite]
|
18
|
+
@cfg = FluxboxAppsMenu::Config.new
|
19
|
+
@fmenu = FluxboxAppsMenu::Menu.new(@cfg)
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_menu
|
23
|
+
if @overwrite == false
|
24
|
+
if File.exists?(File.expand_path("~/.fluxbox/#{@filename}"))
|
25
|
+
puts "The file #{@filename} already exists!" unless @silent
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
scan_app_folder
|
31
|
+
text = @fmenu.render
|
32
|
+
File.open(File.expand_path("~/.fluxbox/#{@filename}"), 'w') { |f| f.write(text) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def init_config
|
36
|
+
unless @overwrite
|
37
|
+
if File.exists?(File.expand_path("~/.fluxbox/fluxbox_apps_menu.yaml"))
|
38
|
+
puts '[Error] '.bold.red + "The file 'fluxbox_apps_menu.yaml' already exists in '#{File.expand_path('~/.fluxbox')}'" unless @silent
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
end
|
42
|
+
FileUtils.copy(File.dirname(__FILE__) + '/fluxbox_apps_menu.yaml', File.expand_path('~/.fluxbox/'))
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def scan_app_folder
|
48
|
+
@cfg.app_paths.each do |d|
|
49
|
+
|
50
|
+
Dir.glob(d + '/*.desktop') do |f|
|
51
|
+
|
52
|
+
ini = DesktopFile.new(f, @cfg)
|
53
|
+
|
54
|
+
next if ini.banned_file?
|
55
|
+
|
56
|
+
name = ini.name
|
57
|
+
|
58
|
+
if ini.hidden?
|
59
|
+
puts '[Hidden] '.bold.green + "The application #{name} is hidden" unless @silent
|
60
|
+
next
|
61
|
+
end
|
62
|
+
|
63
|
+
cat = ini.categories
|
64
|
+
if cat.nil?
|
65
|
+
puts '[No Category] '.bold.red + "The application #{name} doesn't have any category" unless @silent
|
66
|
+
next
|
67
|
+
end
|
68
|
+
|
69
|
+
submenu = @fmenu.assign_menu(cat, name)
|
70
|
+
unless submenu.nil?
|
71
|
+
icon = ini.icon
|
72
|
+
if icon.nil?
|
73
|
+
puts '[No Icon] '.bold.yellow + "#{name} doesn't have any icon" unless @silent
|
74
|
+
end
|
75
|
+
|
76
|
+
submenu[name] = @fmenu.item_exec(name, icon, ini.exec)
|
77
|
+
else
|
78
|
+
puts "[No mapped category] #{name} doesn't have any mapped category within the menu".bold.red unless @silent
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
---
|
2
|
+
# other options: kdesu and gnomesu
|
3
|
+
:switch_user: 'xdg-su'
|
4
|
+
:terminal: 'xdg-terminal'
|
5
|
+
:icons:
|
6
|
+
App Name: 'icon-name'
|
7
|
+
:banned_files:
|
8
|
+
- 'qmmp_.*'
|
9
|
+
- 'umplayer_.*'
|
10
|
+
:icon_paths:
|
11
|
+
- /usr/share/icons/gnome/16x16/apps
|
12
|
+
- /usr/share/icons/oxygen/16x16/apps
|
13
|
+
- /usr/share/icons/hicolor/16x16/apps
|
14
|
+
- /usr/share/pixmaps
|
15
|
+
- /usr/share/icons/hicolor/32x32/apps
|
16
|
+
- /usr/share/icons/oxygen/16x16/categories
|
17
|
+
- /usr/share/icons/hicolor/48x48/apps
|
18
|
+
- /usr/share/icons/hicolor/128x128/apps
|
19
|
+
:app_paths:
|
20
|
+
- /usr/share/applications
|
21
|
+
- /usr/share/applications/kde4
|
22
|
+
- /usr/share/applications/YaST2
|
23
|
+
:menu:
|
24
|
+
Development:
|
25
|
+
:icon: applications-development
|
26
|
+
:categories:
|
27
|
+
- Development
|
28
|
+
Educational:
|
29
|
+
:icon: applications-education-science
|
30
|
+
:categories:
|
31
|
+
- Science
|
32
|
+
- Astronomy
|
33
|
+
- Education
|
34
|
+
- Geography
|
35
|
+
Games:
|
36
|
+
:icon: applications-games
|
37
|
+
:categories:
|
38
|
+
- Game
|
39
|
+
- CardGame
|
40
|
+
Graphic:
|
41
|
+
:icon: applications-graphics
|
42
|
+
:categories:
|
43
|
+
- Graphics
|
44
|
+
- VectorGraphics
|
45
|
+
Internet:
|
46
|
+
:icon: applications-internet
|
47
|
+
:categories:
|
48
|
+
- Network
|
49
|
+
Multimedia:
|
50
|
+
:icon: applications-multimedia
|
51
|
+
:categories:
|
52
|
+
- Audio
|
53
|
+
- Video
|
54
|
+
- Player
|
55
|
+
- AudioVideoEditing
|
56
|
+
- Mixer
|
57
|
+
- Recorder
|
58
|
+
- DiscBurning
|
59
|
+
Office:
|
60
|
+
:icon: applications-office
|
61
|
+
:categories:
|
62
|
+
- Office
|
63
|
+
LibreOffice Draw: ''
|
64
|
+
System:
|
65
|
+
:icon: applications-system
|
66
|
+
:categories:
|
67
|
+
- Settings
|
68
|
+
- System
|
69
|
+
- DesktopSettings
|
70
|
+
- Documentation
|
71
|
+
'. / Yast /':
|
72
|
+
:icon: yast-mascot
|
73
|
+
:categories:
|
74
|
+
- Yast
|
75
|
+
Hardware:
|
76
|
+
:icon: package_yast_hardware
|
77
|
+
:categories:
|
78
|
+
- X-SuSE-YaST-Hardware
|
79
|
+
Miscellaneous:
|
80
|
+
:icon: package_yast_misc
|
81
|
+
:categories:
|
82
|
+
- X-SuSE-YaST-Misc
|
83
|
+
Network Devices:
|
84
|
+
:icon: yast-network_devices
|
85
|
+
:categories:
|
86
|
+
- X-SuSE-YaST-Network
|
87
|
+
Network Services:
|
88
|
+
:icon: yast-network_services
|
89
|
+
:categories:
|
90
|
+
- X-SuSE-YaST-Net_advanced
|
91
|
+
Security and Users:
|
92
|
+
:icon: yast-security
|
93
|
+
:categories:
|
94
|
+
- X-SuSE-YaST-Security
|
95
|
+
System:
|
96
|
+
:icon: package_yast_system
|
97
|
+
:categories:
|
98
|
+
- X-SuSE-YaST-System
|
99
|
+
Software:
|
100
|
+
:icon: yast-software
|
101
|
+
:categories:
|
102
|
+
- X-SuSE-YaST-Software
|
103
|
+
Support:
|
104
|
+
:icon: yast-support
|
105
|
+
:categories:
|
106
|
+
- X-SuSE-YaST-Support
|
107
|
+
Utility:
|
108
|
+
:icon: applications-utilities
|
109
|
+
:categories:
|
110
|
+
- Archiving
|
111
|
+
- Utility
|
112
|
+
'. / Text Files /':
|
113
|
+
:icon: accessories-text-editor
|
114
|
+
:categories:
|
115
|
+
- TextEditor
|
116
|
+
'. / File Managers /':
|
117
|
+
:icon: system-file-manager
|
118
|
+
:categories:
|
119
|
+
- FileManager
|
120
|
+
'. / Terminal Emulators /':
|
121
|
+
:icon: utilities-terminal
|
122
|
+
:categories:
|
123
|
+
- TerminalEmulator
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'fluxbox_apps_menu'
|
3
|
+
require 'fluxbox_apps_menu/version'
|
4
|
+
|
5
|
+
module FluxboxAppsMenu
|
6
|
+
|
7
|
+
class CLI < Thor
|
8
|
+
|
9
|
+
desc 'build', 'Build the menu'
|
10
|
+
method_option :filename, :aliases => '-f', :default => '', :desc => 'Save as filename.'
|
11
|
+
method_option :silent, :aliases => '-s', :default => false, :type => :boolean, :desc => 'Don\'t show any output message.'
|
12
|
+
method_option :overwrite, :aliases => '-o', :default => true, :type => :boolean, :desc => 'Overwrite the app menu if exists.'
|
13
|
+
def build
|
14
|
+
FluxboxAppsMenu::Builder.new(options).create_menu
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'menuconfig', 'Make a local copy of the configuration file.'
|
18
|
+
method_option :overwrite, :aliases => '-o', :default => false, :type => :boolean, :desc => 'Overwrite the config file if exists.'
|
19
|
+
def menuconfig
|
20
|
+
FluxboxAppsMenu::Builder.new(options).init_config
|
21
|
+
end
|
22
|
+
|
23
|
+
def help(arg = nil)
|
24
|
+
if arg.nil?
|
25
|
+
puts <<EOL
|
26
|
+
FluxboxAppsMenu v.#{FluxboxAppsMenu::VERSION} by Fabio Mucciante
|
27
|
+
|
28
|
+
Description:
|
29
|
+
Build a Fluxbox menu putting the applications in the right
|
30
|
+
section as configured within the "fluxbox_apps_menu.yaml" file.
|
31
|
+
|
32
|
+
Using the "menuconfig" task a copy of this file will be created
|
33
|
+
under the "~/.fluxbox" path.
|
34
|
+
|
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
|
+
[include] (~/.fluxbox/menu-apps)
|
39
|
+
|
40
|
+
EOL
|
41
|
+
super
|
42
|
+
else
|
43
|
+
super arg
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
default_task :build
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module FluxboxAppsMenu
|
4
|
+
class Config
|
5
|
+
attr_reader :lang, :icon_paths, :filename, :banned_files, :app_paths, :icons, :terminal
|
6
|
+
attr_accessor :menu
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
if File.exists?(ENV['HOME'] + '/.fluxbox/fluxbox_apps_menu.yaml')
|
10
|
+
@filename = ENV['HOME'] + '/.fluxbox/fluxbox_apps_menu.yaml'
|
11
|
+
elsif File.exists?(ENV['HOME'] + '/.fluxbox_apps_menu.yaml')
|
12
|
+
@filename = ENV['HOME'] + '/.fluxbox_apps_menu.yaml'
|
13
|
+
elsif File.exists?('/etc/fluxbox_apps_menu.yaml')
|
14
|
+
@filename = '/etc/fluxbox_apps_menu.yaml'
|
15
|
+
else
|
16
|
+
@filename = File.expand_path(File.dirname(__FILE__) + '/../fluxbox_apps_menu.yaml')
|
17
|
+
end
|
18
|
+
|
19
|
+
yaml = YAML.load_file(@filename)
|
20
|
+
|
21
|
+
@banned_files = yaml[:banned_files]
|
22
|
+
@icon_paths = yaml[:icon_paths]
|
23
|
+
@app_paths = yaml[:app_paths] + [ ENV['HOME'] + '/.local/share/applications']
|
24
|
+
@menu = yaml[:menu]
|
25
|
+
@icons = yaml[:icons]
|
26
|
+
@terminal = yaml[:terminal]
|
27
|
+
|
28
|
+
@lang = ENV['LANG'].split('.')[0]
|
29
|
+
@lang = { :short => @lang.split('_')[0], :long => @lang }
|
30
|
+
end
|
31
|
+
|
32
|
+
def expand_icon(app_name, icon_name)
|
33
|
+
iname = @icons[app_name] unless app_name.nil?
|
34
|
+
iname = icon_name if iname.nil?
|
35
|
+
|
36
|
+
return nil if iname.to_s.empty?
|
37
|
+
return iname if iname.to_s.match('/') && File.exists?(iname)
|
38
|
+
|
39
|
+
iname.gsub!(/\.png$/, '')
|
40
|
+
|
41
|
+
@icon_paths.each do |p|
|
42
|
+
return "#{p}/#{iname}.png" if File.exists?("#{p}/#{iname}.png")
|
43
|
+
end
|
44
|
+
|
45
|
+
return nil
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'inifile'
|
2
|
+
#require 'fluxbox_apps_menu/config'
|
3
|
+
module FluxboxAppsMenu
|
4
|
+
|
5
|
+
class DesktopFile
|
6
|
+
|
7
|
+
def initialize(filename, cfg = nil)
|
8
|
+
@ini = IniFile.new(:filename => filename, :comment => '#', :encoding => 'UTF-8')
|
9
|
+
@cfg = cfg.nil? ? FluxboxAppsMenu::Config.new : cfg
|
10
|
+
@filename = filename
|
11
|
+
end
|
12
|
+
|
13
|
+
def name(lang = true)
|
14
|
+
if lang
|
15
|
+
name = @ini['Desktop Entry']["Name[#{@cfg.lang[:short]}]"]
|
16
|
+
name = @ini['Desktop Entry']["Name[#{@cfg.lang[:long]}]"] if name.nil?
|
17
|
+
end
|
18
|
+
|
19
|
+
name = @ini['Desktop Entry']['Name'] if name.nil?
|
20
|
+
|
21
|
+
name
|
22
|
+
end
|
23
|
+
|
24
|
+
def hidden?
|
25
|
+
@ini['Desktop Entry']['NoDisplay'] == true
|
26
|
+
end
|
27
|
+
|
28
|
+
def banned_file?
|
29
|
+
@cfg.banned_files.each { |r| return true if @filename =~ Regexp.new(r) }
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def icon
|
34
|
+
=begin
|
35
|
+
iname = @cfg.icons[name(false)]
|
36
|
+
iname = @ini['Desktop Entry']['Icon'] if iname.nil?
|
37
|
+
|
38
|
+
return nil if iname.to_s.empty?
|
39
|
+
return iname if iname.to_s.match('/') && File.exists?(iname)
|
40
|
+
|
41
|
+
iname.gsub!(/\.png$/, '')
|
42
|
+
|
43
|
+
@cfg.icon_paths.each do |p|
|
44
|
+
return "#{p}/#{iname}.png" if File.exists?("#{p}/#{iname}.png")
|
45
|
+
end
|
46
|
+
return nil
|
47
|
+
=end
|
48
|
+
@cfg.expand_icon(name(false), @ini['Desktop Entry']['Icon'])
|
49
|
+
end
|
50
|
+
|
51
|
+
def terminal?
|
52
|
+
@ini['Desktop Entry']['Terminal'] == 'true'
|
53
|
+
end
|
54
|
+
|
55
|
+
def categories
|
56
|
+
cat = @ini['Desktop Entry']['Categories']
|
57
|
+
cat.split(';') unless cat.nil?
|
58
|
+
end
|
59
|
+
|
60
|
+
def exec
|
61
|
+
com = @ini['Desktop Entry']['Exec'].to_s.gsub('%c', name).gsub('%F', '')
|
62
|
+
.gsub('%i', '').gsub('%U', '').gsub('%f', '').gsub('%m', '')
|
63
|
+
.gsub('%u', '').gsub(/[ ]{2,}/, ' ').gsub(/\ }/, '}')
|
64
|
+
|
65
|
+
terminal? ? @cfg.terminal + ' ' + com : com
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|