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
|
#!/usr/bin/env python3
import sys, os
global dictionary_name, sought_word, display_envs, x_reads, reads, wordmod, standard_page_remap, load_dictionary, open_dictionary
## Parse command line.
if len(sys.argv) == 2 and sys.argv[1] == '-l':
f_list = True
elif len(sys.argv) != 3:
print('Usage: dlu [DICTIONARY WORD | -l]', file = sys.stderr)
sys.exit(1)
else:
dictionary_name = sys.argv[1]
sought_word = sys.argv[2]
f_list = False
# Default functions, can be overriden by configurations on call to load_dictionary.
if not f_list:
display_envs = ['MDS_DISPLAY', 'MIR_DISPLAY', 'WAYLAND_DISPLAY', 'DISPLAY']
x_reads = [
(lambda f, p : ['atril', f, '-i', p]),
(lambda f, p : ['evince', f, '-i', p]),
(lambda f, p : ['xpdf', f, p]),
]
reads = dict((disp, list(x_reads)) for disp in display_envs)
reads[None] = [lambda f, p : ['jfbview', '-p', p, '--', f]]
wordmod = lambda x : x.lower()
def standard_page_remap(offset, multiple = 1, multiple_offset = 0):
return lambda p : (0 if p < multiple_offset else p - multiple_offset) // multiple + offset
def open_dictionary(filename, page):
disps = [disp for disp in display_envs if disp in os.environ] + [None]
for command_lambda in reads[disps[0]]:
command = command_lambda(filename, str(page));
os.execvp(command[0], command)
sys.stderr.print("%s: could find any viewer to use." % sys.argv[0])
sys.stderr.print("%s: file to open: %s" % (sys.argv[0], filename))
sys.stderr.print("%s: page to open: %i" % (sys.argv[0], page))
sys.exit(1)
## Load configurations, which holds data needed to perform the lookup.
g, l = globals(), dict(locals())
for key in l:
g[key] = l[key]
# Possible auto-selected configuration scripts,
# earlier ones have precedence, we can only select one.
for file in ('$XDG_CONFIG_HOME/%/%rc', '$HOME/.config/%/%rc', '$HOME/.%rc', '$~/.config/%/%rc', '$~/.%rc', '/etc/%rc'):
# Expand short-hands
file = file.replace('/', os.sep).replace('%', 'dlu')
# Expand environment variables
for arg in ('XDG_CONFIG_HOME', 'HOME'):
# Environment variables are prefixed with $
if '$' + arg in file:
if arg in os.environ:
# To be sure that do so no treat a $ as a variable prefix
# incorrectly we replace any $ in the value of the variable
# with NUL which is not a value pathname character.
file = file.replace('$' + arg, os.environ[arg].replace('$', '\0'))
else:
file = None
break
# Proceed if there where no errors.
if file is not None:
# With use $~ (instead of ~) for the user's proper home
# directroy. HOME should be defined, but it could be missing.
# It could also be set to another directory.
if file.startswith('$~'):
import pwd
# Get the home (also known as initial) directory
# of the real user, and the rest of the path.
file = pwd.getpwuid(os.getuid()).pw_dir + file[2:]
# Now that we are done we can change back any NUL to $:s.
file = file.replace('\0', '$')
# If the file we exists,
if os.path.exists(file):
# select it,
config_file = file
# and stop trying files with lower precedence.
break
if config_file is not None:
code = None
# Read configuration script file.
with open(config_file, 'rb') as script:
code = script.read()
# Decode configurion script file and add a line break
# at the end to ensure that the last line is empty.
# If it is not, we will get errors.
code = code.decode('utf-8', 'strict') + '\n'
# Compile the configuration script,
code = compile(code, config_file, 'exec')
# and run it, with it have the same
# globals as this module, so that it can
# not only use want we have defined, but
# also redefine it for us.
exec(code, g)
else:
print('No configuration file found')
sys.exit(1)
## List available dictionaries.
if f_list:
for d in list_dictionaries():
print(d)
sys.exit(0)
## Perform lookup.
load_dictionary(dictionary_name)
sought_word = wordmod(sought_word)
filename, lasts, page_remap = get()
lasts = [(i, word) for i, word in enumerate(lasts)]
for i, word in lasts:
word = wordmod(word)
if sought_word <= word:
page = i
break
else:
page = lasts[-1][0]
page = page_remap(page)
open_dictionary(filename, page)
|