192 |
- |
1 |
#!/usr/libexec/platform-python
|
|
|
2 |
###############################################################################
|
|
|
3 |
# BRLTTY - A background process providing access to the console screen (when in
|
|
|
4 |
# text mode) for a blind person using a refreshable braille display.
|
|
|
5 |
#
|
|
|
6 |
# Copyright (C) 1995-2018 by The BRLTTY Developers.
|
|
|
7 |
#
|
|
|
8 |
# BRLTTY comes with ABSOLUTELY NO WARRANTY.
|
|
|
9 |
#
|
|
|
10 |
# This is free software, placed under the terms of the
|
|
|
11 |
# GNU Lesser General Public License, as published by the Free Software
|
|
|
12 |
# Foundation; either version 2.1 of the License, or (at your option) any
|
|
|
13 |
# later version. Please see the file LICENSE-LGPL for details.
|
|
|
14 |
#
|
|
|
15 |
# Web Page: http://brltty.com/
|
|
|
16 |
#
|
|
|
17 |
# This software is maintained by Dave Mielke <dave@mielke.cc>.
|
|
|
18 |
###############################################################################
|
|
|
19 |
|
|
|
20 |
# BRLTTY Contraction Table - latex-access (executable)
|
|
|
21 |
|
|
|
22 |
import sys, os
|
|
|
23 |
|
|
|
24 |
def putProgramMessage (message):
|
|
|
25 |
stream = sys.stderr
|
|
|
26 |
stream.write(os.path.basename(sys.argv[0]) + ": " + message + "\n")
|
|
|
27 |
stream.flush()
|
|
|
28 |
|
|
|
29 |
def syntaxError (message):
|
|
|
30 |
putProgramMessage(message)
|
|
|
31 |
exit(2)
|
|
|
32 |
|
|
|
33 |
def semanticError (message):
|
|
|
34 |
putProgramMessage(message)
|
|
|
35 |
exit(3)
|
|
|
36 |
|
|
|
37 |
def systemError (message):
|
|
|
38 |
putProgramMessage(message)
|
|
|
39 |
exit(4)
|
|
|
40 |
|
|
|
41 |
def missingPackage (name):
|
|
|
42 |
systemError("package not installed: " + name)
|
|
|
43 |
|
|
|
44 |
def putResponseProperty (keyword, value):
|
|
|
45 |
value = str(value)
|
|
|
46 |
if programArguments.verbose: putProgramMessage("rsp: " + keyword + "=" + value)
|
|
|
47 |
|
|
|
48 |
stream = sys.stdout
|
|
|
49 |
stream.write(keyword + "=" + value.encode("UTF-8") + "\n")
|
|
|
50 |
stream.flush()
|
|
|
51 |
|
|
|
52 |
def getRequest ():
|
|
|
53 |
request = {}
|
|
|
54 |
|
|
|
55 |
while True:
|
|
|
56 |
try:
|
|
|
57 |
if programArguments.interactive:
|
|
|
58 |
line = input(packageName + "> ")
|
|
|
59 |
else:
|
|
|
60 |
line = input()
|
|
|
61 |
except EOFError:
|
|
|
62 |
if len(request) == 0: return None
|
|
|
63 |
semanticError("unexpected end-of-file on standard input")
|
|
|
64 |
|
|
|
65 |
line = line.decode("UTF-8")
|
|
|
66 |
components = line.split("=", 1)
|
|
|
67 |
|
|
|
68 |
if len(components) > 1:
|
|
|
69 |
(keyword, value) = components
|
|
|
70 |
keyword = keyword.strip().lower()
|
|
|
71 |
|
|
|
72 |
if programArguments.verbose: putProgramMessage("req: " + keyword + "=" + value)
|
|
|
73 |
request[keyword] = value
|
|
|
74 |
if keyword == "text": break
|
|
|
75 |
|
|
|
76 |
return request
|
|
|
77 |
|
|
|
78 |
def processRequest ():
|
|
|
79 |
request = getRequest()
|
|
|
80 |
if not request: return False
|
|
|
81 |
|
|
|
82 |
for attribute in ("displayLength", "cursorOffset", "expandCurrentWord", "consumedChars"):
|
|
|
83 |
if hasattr(brailleTranslator, attribute):
|
|
|
84 |
delattr(brailleTranslator, attribute)
|
|
|
85 |
|
|
|
86 |
if "maximum-length" in request:
|
|
|
87 |
brailleTranslator.displayLength = int(request["maximum-length"])
|
|
|
88 |
|
|
|
89 |
if "cursor-position" in request:
|
|
|
90 |
position = int(request["cursor-position"])
|
|
|
91 |
|
|
|
92 |
if position > 0:
|
|
|
93 |
brailleTranslator.cursorOffset = position - 1
|
|
|
94 |
|
|
|
95 |
if "expand-current-word" in request:
|
|
|
96 |
brailleTranslator.expandCurrentWord = int(request["expand-current-word"]) != 0
|
|
|
97 |
|
|
|
98 |
brailleTranslator.capitalisation = "6dot"
|
|
|
99 |
if "capitalization-mode" in request:
|
|
|
100 |
if int(request["capitalization-mode"]) != 1:
|
|
|
101 |
brailleTranslator.capitalisation = "8dot"
|
|
|
102 |
|
|
|
103 |
text = request["text"]
|
|
|
104 |
brf = brailleTranslator.translate(textPreprocessor.translate(text))
|
|
|
105 |
|
|
|
106 |
if hasattr(brailleTranslator, "consumedChars"):
|
|
|
107 |
consumedLength = brailleTranslator.consumedChars
|
|
|
108 |
putResponseProperty("consumed-length", consumedLength)
|
|
|
109 |
else:
|
|
|
110 |
consumedLength = len(text)
|
|
|
111 |
|
|
|
112 |
if hasattr(brailleTranslator, "src2trans"):
|
|
|
113 |
offsets = brailleTranslator.src2trans
|
|
|
114 |
if len(offsets) > consumedLength: offsets = offsets[:consumedLength]
|
|
|
115 |
putResponseProperty("output-offsets", ",".join((str(offset) for offset in offsets)))
|
|
|
116 |
|
|
|
117 |
putResponseProperty("brf", brf)
|
|
|
118 |
return True
|
|
|
119 |
|
|
|
120 |
def parseProgramArguments ():
|
|
|
121 |
import argparse
|
|
|
122 |
parser = argparse.ArgumentParser(
|
|
|
123 |
prog = os.path.basename(sys.argv[0]),
|
|
|
124 |
usage = "%(prog)s [option ...]",
|
|
|
125 |
description = """
|
|
|
126 |
This is an executable contraction table for BRLTTY
|
|
|
127 |
that uses the latex-access package
|
|
|
128 |
to translate LaTeX mathematical notation into braille.
|
|
|
129 |
BRLTTY can be found at [http://brltty.com/].
|
|
|
130 |
latex-access can be found at [http://www.latex-access.sourceforge.net/].
|
|
|
131 |
"""
|
|
|
132 |
)
|
|
|
133 |
|
|
|
134 |
parser.add_argument(
|
|
|
135 |
"-c", "--configuration",
|
|
|
136 |
action = "store",
|
|
|
137 |
nargs = 1,
|
|
|
138 |
dest = "configuration",
|
|
|
139 |
default = (
|
|
|
140 |
os.path.join(os.path.expanduser("~"), "." + packageName),
|
|
|
141 |
"/etc/" + packageName + ".conf"
|
|
|
142 |
),
|
|
|
143 |
help = "the configuration file to use"
|
|
|
144 |
)
|
|
|
145 |
|
|
|
146 |
parser.add_argument(
|
|
|
147 |
"-n", "--nemeth",
|
|
|
148 |
action = "store_const",
|
|
|
149 |
const = "nemeth",
|
|
|
150 |
dest = "translator",
|
|
|
151 |
help = "translate into Nemeth Code"
|
|
|
152 |
)
|
|
|
153 |
|
|
|
154 |
parser.add_argument(
|
|
|
155 |
"-u", "--ueb",
|
|
|
156 |
action = "store_const",
|
|
|
157 |
const = "ueb",
|
|
|
158 |
dest = "translator",
|
|
|
159 |
help = "translate into Unified English Braille"
|
|
|
160 |
)
|
|
|
161 |
|
|
|
162 |
parser.add_argument(
|
|
|
163 |
"-i", "--interactive",
|
|
|
164 |
action = "store_true",
|
|
|
165 |
dest = "interactive",
|
|
|
166 |
help = "enable input editing and history"
|
|
|
167 |
)
|
|
|
168 |
|
|
|
169 |
parser.add_argument(
|
|
|
170 |
"-v", "--verbose",
|
|
|
171 |
action = "store_true",
|
|
|
172 |
dest = "verbose",
|
|
|
173 |
help = "show request and response properties on standard error"
|
|
|
174 |
)
|
|
|
175 |
|
|
|
176 |
return parser.parse_args()
|
|
|
177 |
|
|
|
178 |
if __name__ == "__main__":
|
|
|
179 |
packageName = "latex-access"
|
|
|
180 |
|
|
|
181 |
programArguments = parseProgramArguments()
|
|
|
182 |
|
|
|
183 |
if programArguments.interactive:
|
|
|
184 |
import readline, atexit
|
|
|
185 |
historyFile=os.path.join(os.path.expanduser("~"), "." + packageName + ".history")
|
|
|
186 |
atexit.register(readline.write_history_file, historyFile)
|
|
|
187 |
readline.read_history_file(historyFile)
|
|
|
188 |
|
|
|
189 |
try:
|
|
|
190 |
from latex_access import nemeth, ueb, preprocessor, settings
|
|
|
191 |
except ImportError:
|
|
|
192 |
missingPackage(packageName)
|
|
|
193 |
|
|
|
194 |
for configurationFile in programArguments.configuration:
|
|
|
195 |
if os.path.exists(configurationFile):
|
|
|
196 |
if programArguments.verbose:
|
|
|
197 |
putProgramMessage("configuration file: " + configurationFile)
|
|
|
198 |
|
|
|
199 |
settings.loadSettings(configurationFile)
|
|
|
200 |
break
|
|
|
201 |
|
|
|
202 |
if programArguments.translator:
|
|
|
203 |
settings.settings["brailletable"] = programArguments.translator
|
|
|
204 |
|
|
|
205 |
brailleTranslator = settings.brailleTableToUse()
|
|
|
206 |
textPreprocessor = preprocessor.preprocessor()
|
|
|
207 |
|
|
|
208 |
settings.activateSettings(
|
|
|
209 |
{
|
|
|
210 |
"braille": brailleTranslator,
|
|
|
211 |
"preprocessor": textPreprocessor
|
|
|
212 |
}
|
|
|
213 |
)
|
|
|
214 |
|
|
|
215 |
while processRequest(): pass
|
|
|
216 |
|