3
|
1 #!/usr/bin/env python3
|
|
2 # -*- coding: utf-8 -*-
|
|
3
|
|
4 import os, sys
|
|
5 import argparse
|
|
6 import codecs
|
|
7
|
4
|
8 from curlers import TextCurler, HtmlCurler, uncurl
|
10
|
9 from runes import Workspace
|
3
|
10 from writer import CODECS_TO_NAME
|
|
11
|
|
12 # V a r i a b l e s
|
|
13
|
|
14 # Name invoked by
|
|
15 MYNAME = os.path.basename(sys.argv[0])
|
|
16
|
|
17 # Streams
|
|
18 input_fp = None
|
|
19 output_fp = None
|
|
20
|
|
21 # F u n c t i o n s
|
|
22
|
|
23 def normal():
|
4
|
24 global input_fp, output_fp, args
|
10
|
25 ws = Workspace()
|
|
26 curler = TextCurler(ws)
|
|
27 while True:
|
|
28 line = input_fp.readline()
|
|
29 ws.append(line)
|
|
30 if line == "" or line == "\n":
|
|
31 if args.force: uncurl(ws)
|
|
32 curler.feed()
|
|
33 output_fp.write(str(ws))
|
|
34 ws.clear()
|
|
35 if line == "":
|
|
36 break
|
3
|
37
|
|
38 def flowed():
|
|
39 global input_fp, output_fp, args
|
10
|
40 ws = Workspace()
|
|
41 curler = TextCurler(ws)
|
|
42 while True:
|
|
43 line = input_fp.readline()
|
|
44 if line == "":
|
|
45 break
|
|
46 ws.append(line)
|
|
47 if args.force: uncurl(ws)
|
|
48 curler.feed()
|
|
49 output_fp.write(str(ws))
|
|
50 ws.clear()
|
3
|
51
|
|
52 def html():
|
|
53 global input_fp, output_fp
|
10
|
54 ws = Workspace(input_fp.read())
|
|
55 curler = HtmlCurler(ws)
|
|
56 if args.force: uncurl(ws)
|
|
57 curler.feed()
|
|
58 output_fp.write(str(ws))
|
3
|
59
|
5
|
60 def do_uncurl():
|
|
61 global input_fp, output_fp
|
10
|
62 ws = Workspace(input_fp.read())
|
|
63 uncurl(ws)
|
|
64 output_fp.write(str(ws))
|
5
|
65
|
3
|
66 # M a i n P r o g r a m
|
|
67
|
|
68 # Parse arguments
|
8
|
69 parser = argparse.ArgumentParser(
|
|
70 description='Make straight quotes curly.', prog=MYNAME)
|
3
|
71 group = parser.add_mutually_exclusive_group()
|
|
72 group.add_argument("--flowed", action="store_true", help="Input is flowed text.")
|
|
73 group.add_argument("--html", action="store_true", help="Input is HTML.")
|
5
|
74 group.add_argument("--uncurl", action="store_true", help="Uncurl quotes instead of curling them.")
|
3
|
75 parser.add_argument("--force", action="store_true", help="Force all quotes to straight ones first.")
|
8
|
76 parser.add_argument("--icoding", default="UTF-8", help="Input encoding (default UTF-8).")
|
3
|
77 parser.add_argument("--inplace", action="store_true", help="Edit file in-place.")
|
8
|
78 parser.add_argument("--ocoding", default="UTF-8", help="Output encoding (default UTF-8).")
|
3
|
79 parser.add_argument("input", nargs="?", help="Input file.")
|
|
80 parser.add_argument("output", nargs="?", help="Output file.")
|
|
81 try:
|
|
82 args = parser.parse_args()
|
|
83 except SystemExit:
|
|
84 sys.exit(2)
|
|
85
|
|
86 # Sanity-check codings
|
|
87 try:
|
|
88 codec = codecs.lookup(args.icoding)
|
|
89 codec = codecs.lookup(args.ocoding)
|
|
90 except LookupError as e:
|
|
91 sys.stderr.write("{0}: {1!s}\n".format(MYNAME, e))
|
|
92 sys.exit(2)
|
|
93 if not CODECS_TO_NAME.get(codec, "").startswith("UTF-"):
|
8
|
94 sys.stderr.write("{0}: {1!r} output coding does not support Unicode\n".format(MYNAME, args.ocoding))
|
3
|
95 sys.exit(1)
|
|
96 del codec
|
|
97
|
|
98 # Get streams
|
|
99 try:
|
|
100 if args.input and (not args.output) and args.inplace:
|
|
101 args.output = args.input
|
|
102 args.input += "~"
|
5
|
103 os.rename(args.output, args.input)
|
3
|
104 if args.input:
|
|
105 input_fp = open(args.input, "r", encoding=args.icoding)
|
|
106 else:
|
|
107 input_fp = open(0, "r", encoding=args.icoding)
|
|
108 if args.output:
|
|
109 output_fp = open(args.output, "w", encoding=args.ocoding)
|
|
110 else:
|
|
111 output_fp = open(1, "w", encoding=args.ocoding)
|
|
112 except (OSError, LookupError) as e:
|
|
113 sys.stderr.write("{0}: {1!s}\n".format(MYNAME, e))
|
|
114 sys.exit(1)
|
|
115
|
|
116 # Choose our mode
|
|
117 if args.flowed:
|
|
118 flowed()
|
|
119 elif args.html:
|
|
120 html()
|
5
|
121 elif args.uncurl:
|
|
122 do_uncurl()
|
3
|
123 else:
|
|
124 normal()
|