1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
# -*- python -*-
'''
xpybar – xmobar replacement written in python
Copyright © 2014, 2015, 2016, 2017 Mattias Andrée (maandree@member.fsf.org)
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.
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.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''
class Application:
'''
Applications and .desktop files
@variable desktop_file:str The .desktop file for the application
@variable settings:dict<str?, dict<str, dict<str?, str>>> Section → key → locale → value map of settings
'''
def __init__(self, file):
'''
Constructor
@param file:str The .desktop file if it contains '/', otherwise the name of the application
'''
import os
if '/' not in file:
import pwd
directories = []
home = pwd.getpwuid(os.getuid()).pw_dir
directories.append('%s/.local/share/applications' % home)
if 'HOME' in os.environ:
if not os.environ['HOME'] == home:
home = os.environ['HOME']
directories.append('%s/.local/share/applications' % home)
directories += ['/usr/local/share/applications', '/usr/share/applications', '/share/applications']
directories = [d for d in directories if os.path.exists(d) and os.path.isdir(d)]
file = ['%s/%s.desktop' % (d, file) for d in directories]
file = [f for f in file if os.path.exists(f) and os.path.isfile(f)]
if len(file) == 0:
raise Exception('Application not found')
file = file[0]
self.desktop_file = file
with open(self.desktop_file, 'rb') as file:
data = file.read()
data = [l for l in data.decode('utf-8', 'replace').replace('\r', '\n').split('\n') if not l == '']
section = None
self.settings = {}
for line in data:
line = line.strip()
if line.startswith('[') and line.endswith(']'):
section = line[1 : -1]
elif line.startswith(';') or line.startswith('#'):
pass
elif (':' in line) or ('=' in line):
line_e = line.split('=')
line_c = line.split(':')
if len(line_e[0]) < len(line_c[0]):
first = '='
line = line_e
else:
first = ':'
line = line_c
key, value = line[0].rstrip(), first.join(line[1:]).lstrip()
locale = None
if ('[' in key) and key.endswith(']'):
key = key[:-1].split('[')
key, locale = '['.join(key[:-1]), key[-1]
if section not in self.settings:
self.settings[section] = {}
section_map = self.settings[section]
if key not in section_map:
section_map[key] = {}
key_map = section_map[key]
if locale not in key_map:
key_map[locale] = value
self.locales = [None]
if 'LANG' in os.environ:
locale = os.environ['LANG']
elif 'LOCALE' in os.environ:
locale = os.environ['LOCALE']
else:
return
locale = locale.split(' ')[0].split('.')[0].split('_')
for i in range(len(locale)):
self.locales.append('_'.join(locale[:i]))
self.locales.reverse()
def get_setting(self, key, section = 'Desktop Entry', locales = None):
'''
Read a setting in the application's .desktop file
@param key:str The key
@param section:str? The section where the key is located
@param locale:list<str?>? Acceptable locales in order of preference,
`None` to use the default for your locale
'''
map = self.settings
if section not in map:
return None
map = map[section]
if key not in map:
return None
map = map[key]
if locales is None:
locales = self.locales
for locale in locales:
if locale in map:
return map[locale]
return None
@staticmethod
def strip_placeholders(text):
'''
Remove placeholders form an exec string
@param text:str The exec string with placeholders
@return :str The exec string without placeholders
'''
buf, esc = '', False
for c in text:
if esc:
esc = False
if c == '%':
buf += c
elif c == '%':
esc = True
else:
buf += c
return buf
|