Mercurial > cgi-bin > hgweb.cgi > curlyq
annotate curlyq @ 26:3264788aa0c8
Add --tex option.
author | David Barts <n5jrn@me.com> |
---|---|
date | Sun, 22 Mar 2020 08:32:52 -0700 |
parents | f4cc6d8cafe8 |
children | 70e75dd07e03 |
rev | line source |
---|---|
3 | 1 #!/usr/bin/env python3 |
2 # -*- coding: utf-8 -*- | |
3 | |
22
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
4 # I m p o r t s |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
5 |
3 | 6 import os, sys |
7 import argparse | |
8 import codecs | |
9 | |
4 | 10 from curlers import TextCurler, HtmlCurler, uncurl |
10 | 11 from runes import Workspace |
3 | 12 |
13 # V a r i a b l e s | |
14 | |
15 # Name invoked by | |
16 MYNAME = os.path.basename(sys.argv[0]) | |
17 | |
18 # Streams | |
19 input_fp = None | |
20 output_fp = None | |
21 | |
22
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
22 # Codecs we support |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
23 CODECS_TO_NAME = {} |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
24 for i in [ "UTF-8", "UTF-16", "UTF-16LE", "UTF-16BE", "UTF-32", "UTF-32LE", "UTF-32BE" ]: |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
25 CODECS_TO_NAME[codecs.lookup(i)] = i |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
26 del i |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
27 |
23 | 28 # For feet/inches/min/sec |
29 BACKT = "`" | |
30 FTMIN = "'" | |
31 INSEC = '"' | |
32 | |
26 | 33 # For --tex option |
34 TEX_SUBST = [ ("---", "—"), ("--", "–"), ("...", "…") ] | |
35 | |
22
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
36 # C l a s s e s |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
37 |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
38 class SafeWorkspace(Workspace): |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
39 def __getitem__(self, key): |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
40 try: |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
41 return super().__getitem__(key) |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
42 except IndexError: |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
43 return "" |
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
44 |
3 | 45 # F u n c t i o n s |
46 | |
47 def normal(): | |
4 | 48 global input_fp, output_fp, args |
22
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
49 ws = SafeWorkspace() |
10 | 50 curler = TextCurler(ws) |
51 while True: | |
52 line = input_fp.readline() | |
53 ws.append(line) | |
54 if line == "" or line == "\n": | |
55 if args.force: uncurl(ws) | |
56 curler.feed() | |
23 | 57 if args.backtick: fims(ws) |
26 | 58 if args.tex: tex(ws) |
10 | 59 output_fp.write(str(ws)) |
60 ws.clear() | |
61 if line == "": | |
62 break | |
3 | 63 |
64 def flowed(): | |
65 global input_fp, output_fp, args | |
22
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
66 ws = SafeWorkspace() |
10 | 67 curler = TextCurler(ws) |
68 while True: | |
69 line = input_fp.readline() | |
70 if line == "": | |
71 break | |
72 ws.append(line) | |
73 if args.force: uncurl(ws) | |
74 curler.feed() | |
23 | 75 if args.backtick: fims(ws) |
26 | 76 if args.tex: tex(ws) |
10 | 77 output_fp.write(str(ws)) |
78 ws.clear() | |
3 | 79 |
80 def html(): | |
81 global input_fp, output_fp | |
22
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
82 ws = SafeWorkspace(input_fp.read()) |
10 | 83 curler = HtmlCurler(ws) |
84 if args.force: uncurl(ws) | |
85 curler.feed() | |
86 output_fp.write(str(ws)) | |
3 | 87 |
5 | 88 def do_uncurl(): |
89 global input_fp, output_fp | |
22
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
90 ws = SafeWorkspace(input_fp.read()) |
10 | 91 uncurl(ws) |
92 output_fp.write(str(ws)) | |
5 | 93 |
23 | 94 def fims(buf): |
95 pos = 0 | |
96 while True: | |
24 | 97 pos = buf.find(BACKT, pos) |
23 | 98 if pos < 0: |
99 break | |
100 if buf[pos+1] == BACKT: | |
101 buf[pos:pos+2] = INSEC | |
102 else: | |
103 buf[pos] = FTMIN | |
104 pos += 1 | |
105 | |
26 | 106 def gsub(buf, old, repl): |
107 old = Workspace(old) | |
108 repl = Workspace(repl) | |
109 olen = len(old) | |
110 delta = len(repl) | |
111 pos = 0 | |
112 while True: | |
113 pos = buf.find(old, pos) | |
114 if pos < 0: | |
115 break | |
116 buf[pos:pos+olen] = repl | |
117 pos += delta | |
118 | |
119 def tex(buf): | |
120 global TEX_SUBST | |
121 for i in TEX_SUBST: | |
122 gsub(buf, i[0], i[1]) | |
123 | |
3 | 124 # M a i n P r o g r a m |
125 | |
126 # Parse arguments | |
8 | 127 parser = argparse.ArgumentParser( |
128 description='Make straight quotes curly.', prog=MYNAME) | |
3 | 129 group = parser.add_mutually_exclusive_group() |
23 | 130 parser.add_argument("--backtick", action="store_true", help="Use backticks on input for ft/in/min/sec.") |
3 | 131 group.add_argument("--flowed", action="store_true", help="Input is flowed text.") |
132 group.add_argument("--html", action="store_true", help="Input is HTML.") | |
5 | 133 group.add_argument("--uncurl", action="store_true", help="Uncurl quotes instead of curling them.") |
3 | 134 parser.add_argument("--force", action="store_true", help="Force all quotes to straight ones first.") |
8 | 135 parser.add_argument("--icoding", default="UTF-8", help="Input encoding (default UTF-8).") |
3 | 136 parser.add_argument("--inplace", action="store_true", help="Edit file in-place.") |
8 | 137 parser.add_argument("--ocoding", default="UTF-8", help="Output encoding (default UTF-8).") |
26 | 138 parser.add_argument("--tex", action="store_true", help="TeX/LaTeX style dash and ellipsis substitution.") |
3 | 139 parser.add_argument("input", nargs="?", help="Input file.") |
140 parser.add_argument("output", nargs="?", help="Output file.") | |
141 try: | |
142 args = parser.parse_args() | |
143 except SystemExit: | |
144 sys.exit(2) | |
145 | |
26 | 146 # Sanity checks |
23 | 147 if args.html and args.backtick: |
148 sys.stderr.write(MYNAME + ": --backtick not supported in --html mode\n") | |
149 sys.exit(2) | |
26 | 150 if args.html and args.tex: |
151 sys.stderr.write(MYNAME + ": --tex not supported in --html mode\n") | |
152 sys.exit(2) | |
23 | 153 |
3 | 154 # Sanity-check codings |
155 try: | |
156 codec = codecs.lookup(args.icoding) | |
157 codec = codecs.lookup(args.ocoding) | |
158 except LookupError as e: | |
159 sys.stderr.write("{0}: {1!s}\n".format(MYNAME, e)) | |
160 sys.exit(2) | |
22
a771878f6cf4
Remove deadwood, update runes.py.
David Barts <n5jrn@me.com>
parents:
10
diff
changeset
|
161 if codec not in CODECS_TO_NAME: |
8 | 162 sys.stderr.write("{0}: {1!r} output coding does not support Unicode\n".format(MYNAME, args.ocoding)) |
3 | 163 sys.exit(1) |
164 del codec | |
165 | |
166 # Get streams | |
167 try: | |
168 if args.input and (not args.output) and args.inplace: | |
169 args.output = args.input | |
170 args.input += "~" | |
5 | 171 os.rename(args.output, args.input) |
3 | 172 if args.input: |
173 input_fp = open(args.input, "r", encoding=args.icoding) | |
174 else: | |
175 input_fp = open(0, "r", encoding=args.icoding) | |
176 if args.output: | |
177 output_fp = open(args.output, "w", encoding=args.ocoding) | |
178 else: | |
179 output_fp = open(1, "w", encoding=args.ocoding) | |
180 except (OSError, LookupError) as e: | |
181 sys.stderr.write("{0}: {1!s}\n".format(MYNAME, e)) | |
182 sys.exit(1) | |
183 | |
184 # Choose our mode | |
185 if args.flowed: | |
186 flowed() | |
187 elif args.html: | |
188 html() | |
5 | 189 elif args.uncurl: |
190 do_uncurl() | |
3 | 191 else: |
192 normal() |