wtex 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2011 Akira FUNAI <akira -at- funai -dot- com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a
4
+ copy of this software and associated documentation files (the "Software"),
5
+ to deal in the Software without restriction, including without limitation
6
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
7
+ and/or sell copies of the Software, and to permit persons to whom the
8
+ Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19
+ DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,2 @@
1
+ See README.ja.* :-)
2
+ README.en is on the way.
Binary file
@@ -0,0 +1,249 @@
1
+ !!! このソフトについて
2
+
3
+ WTeXは、WikiマークアップとTeXマークアップが混在した文書から、LaTeXでタイプセット可能なTeX文書を生成するユーティリティです。段落・見出し・強調・ルビなどのマークアップを、可読性の高いWiki形式で記述し、make一発でTeX→PDFに変換することができます。また、TeXマークアップを混在させることで、高度なレイアウトや数式も表現可能です。
4
+
5
+ ソース:
6
+ |このように、***Wiki***と{\LARGE\bf TeX}の混在した文書《ソース》から、PDFが作れます。
7
+
8
+ 出力:
9
+ ]このように、***Wiki***と{\LARGE\bf TeX}の混在した文書《ソース》から、PDFが作れます。
10
+
11
+ ※作者本人は、プレーンテキスト→縦書きPDFがやりたかっただけなので、その他の機能はオマケ気味です。それなりに御用心ください。ライセンスにもある通り、完全に無保証です。
12
+
13
+ !!! インストールと実行
14
+
15
+ !! 必要条件
16
+
17
+ WTeXでPDFを出力するには、以下のソフトが必要です。
18
+
19
+ * Ruby 1.8/1.9
20
+ * UTF-8を扱えるLaTeX環境(TeX Live 2010、MacTeXで確認しています)
21
+ * GNU互換make
22
+
23
+ !! インストール
24
+
25
+ | gem install wtex
26
+
27
+ !! PDFの作成
28
+
29
+ 適当なディレクトリで、以下を実行します。
30
+
31
+ | wikitex init my_project
32
+
33
+ 生成されたディレクトリ「my_project」には、以下のファイルがコピーされています。
34
+
35
+ | Makefile
36
+ | body.txt
37
+ | head.tex
38
+ | tmpl.tex.report
39
+ | tmpl.tex.tbook
40
+ | out/
41
+
42
+ 最初に、tmpl.tex.*のいずれかをtmpl.texとしてコピーします。tmpl.tex.reportが横書き、tmpl.tex.tbookが縦書きのサンプルです。
43
+
44
+ | cp -p tmpl.tex.report tmpl.tex
45
+
46
+ body.txtに、Wiki/TeXマークアップでソースを記述します。head.texには文書タイトルや著者情報が、tmpl.texにはTeX文書の外枠がありますので、これらも必要に応じて適宜編集してください。完成したら、
47
+
48
+ | make
49
+
50
+ で、(うまく行けば)ディレクトリ内に「body.tex」および「book.pdf」が生成されます。
51
+
52
+ !! Ruby からの利用
53
+
54
+ | require 'rubygems'
55
+ | require 'wtex'
56
+ |
57
+ | wt = WTeX.new
58
+ | tex = wt.tex '***Wiki***{\LARGE\bf TeX}'
59
+
60
+ !!! マークアップ
61
+
62
+ !! 段落と改行
63
+
64
+ 段落の区切りは空行(TeXと同じです)。
65
+ ただし、TeXと違い、段落内の改行は、そのまま反映されます。
66
+
67
+ 段落頭の字下げは、デフォルトでは手動です。
68
+
69
+ !! Wikiマークアップ
70
+
71
+ ! 見出し
72
+
73
+ 1〜3ケの「!」を行の頭に置くと、それぞれ小節・節・章の見出しになります。また、「!」の直後に「*」を付けると、連番が出力されなくなります。
74
+
75
+ ソース:
76
+ | !!! 章
77
+ | !! 節
78
+ | ! 小節
79
+ | !* 小節(番号なし)
80
+
81
+ ! 区切り
82
+
83
+ ハイフン3つ「---」を行の頭に置くと、小節の区切り記号になります。
84
+
85
+ ---
86
+
87
+ ! 強調
88
+
89
+ 2〜4ヶの「*」で文章を囲むと、その範囲が***強調***(デフォルトでは太字&大文字)されます。「*」を増やすほど、大きな文字になります。
90
+
91
+ ソース:
92
+ | これは****ひどい****。
93
+
94
+ 出力:
95
+ ] これは****ひどい****。
96
+
97
+ ! 傍点・アンダーライン
98
+
99
+ 2ケの「_」で文章を囲むと、その範囲に__傍点__(横書きの場合、アンダーライン)が適用されます。
100
+
101
+ ソース:
102
+ | これは__ひどい__。
103
+
104
+ 出力:
105
+ ] これは__ひどい__。
106
+
107
+ ! ルビ
108
+
109
+ 「\verb|ルビ《るび》|」のように記述すると、ルビ《るび》を振ることができます。ルビの適用範囲は自動的に判定されますが、複合語などの場合、「|」記号で区切ることで、部分|指定《してい》も可能です(青空文庫形式に準拠)。
110
+
111
+ ソース:
112
+ | これは酷《ひど》い三|馬鹿《ばか》ですね。
113
+
114
+ 出力:
115
+ ] これは酷《ひど》い三|馬鹿《ばか》ですね。
116
+
117
+ ! ボックス
118
+
119
+ 行の先頭に「]」記号、または「|」記号を置くと、その行は枠付きボックスとして表示されます。行の直前に「foo.rb:」のようにコロン「:」で終わる行を書くと、ボックスのタイトルとして扱われます。「]」で始まるブロックの内部では、WikiマークアップおよびTeXマークアップが利用可能です。「|」で始まるブロックの内部では、WikiマークアップもTeXマークアップも使用できず、ソースの文字がすべてそのまま表示されます。
120
+
121
+ ソース:
122
+ | foo_bar.tex:
123
+ | ]foo,bar,
124
+ | ]{\large\bf bar},**baz**
125
+
126
+ \begin{WTbox}{出力(マークアップが評価される)}
127
+ \begin{WTbox}{foo\_{}bar.tex}
128
+ foo,bar,\\
129
+ {\large\bf bar},{\large\bf baz}
130
+ \end{WTbox}
131
+ \end{WTbox}
132
+
133
+ ソース:
134
+ | foo_bar.tex:
135
+ | |foo,bar,
136
+ | |{\large\bf bar},**baz**
137
+
138
+ \begin{WTbox}{出力(マークアップは評価されない)}
139
+ \begin{WTcode}{foo\_{}bar.tex}
140
+ foo,bar,
141
+ {\large\bf bar},**baz**
142
+ \end{WTcode}
143
+ \end{WTbox}
144
+
145
+ ! 引用
146
+
147
+ 行の先頭に「>」記号を置くと、その行は引用として扱われます。引用の内部では、WikiマークアップおよびTeXマークアップが利用可能です。
148
+
149
+ ソース:
150
+ | >吾輩は猫である。
151
+ | >名前は__まだ無い__。
152
+
153
+ \begin{WTbox}{出力}
154
+ \begin{quote}
155
+ 吾輩は猫である。\\
156
+ 名前は\WTunderline{まだ無い}。
157
+ \end{quote}
158
+ \end{WTbox}
159
+
160
+ ! リスト
161
+
162
+ 行の先頭に「*」または「+」記号を置くと、その行はリストアイテムとして扱われます。「*」は序数なし、「+」だと序数ありです。強調の「\verb|**foo**|」と区別するため、記号とアイテムの間には、必ず空白を入れてください。
163
+
164
+ ソース:
165
+ | * foo
166
+ | * bar
167
+ | *baz←くっつけて書くとリストにならない
168
+
169
+ \begin{WTbox}{出力}
170
+ \begin{itemize}
171
+ \item foo
172
+ \item bar
173
+ \end{itemize}
174
+ *baz←くっつけて書くとリストにならない
175
+ \end{WTbox}
176
+
177
+ リストを入れ子にすることもできます。
178
+
179
+ ソース:
180
+ | + foo
181
+ | +* bar
182
+ | +* baz
183
+ | + qux
184
+
185
+ \begin{WTbox}{出力}
186
+ \begin{enumerate}
187
+ \item foo\begin{itemize}
188
+ \item bar
189
+ \item baz
190
+ \end{itemize}
191
+
192
+ \item qux
193
+ \end{enumerate}
194
+ \end{WTbox}
195
+
196
+ ! テーブル・表
197
+
198
+ 今のところ、Wikiマークアップはありません。TeXで書きましょう。
199
+
200
+ !! TeXとの混在
201
+
202
+ ! 特殊記号の自動エスケープ
203
+
204
+ TeXの特殊記号は、自動的にエスケープされます。「#」「%」「@」などは、そのまま記述可能です。ただし、バックスラッシュ「\verb|\|」・ドル記号「\${}」・中括弧「\verb|{}|」の3種だけは、\verb|\verb|等によるエスケープが必要です。
205
+
206
+ ソース:
207
+ | #, %, &
208
+ | \verb|\|, \${}, \verb|{}|
209
+
210
+ 出力:
211
+ ] #, %, &
212
+ ] \verb|\|, \${}, \verb|{}|
213
+
214
+ ! TeXコマンド、環境、グルーピング
215
+
216
+ 「\verb|\|」で始まるコマンド、「\verb|\begin{...}...\end{...}|」で指定された環境、「\verb|{...}|」内部のグルーピングは、Wikiをスルーして出力されるので、TeXマークアップをそのまま記述することが可能です。
217
+
218
+ ソース:
219
+ | \verb|***Wiki***|
220
+ | \begin{huge}Wiki《るび》\end{huge}
221
+ | {\large\bf Wiki$\heartsuit$}
222
+
223
+ 出力:
224
+ ] \verb|***Wiki***|
225
+ ] \begin{huge}Wiki《るび》\end{huge}
226
+ ] {\large\bf Wiki$\heartsuit$}
227
+
228
+ ! 数式モード
229
+
230
+ 「\verb|$|」または「\verb|$$|」で囲まれた内部は、TeXの数式モードとして扱われます。
231
+
232
+ ソース:
233
+ | これはひどい $x^2 + \sqrt{y}$ です。
234
+
235
+ 出力(テキスト数式モード):
236
+ ] これはひどい $x^2 + \sqrt{y}$ です。
237
+
238
+ ソース:
239
+ | これはひどい $$x^2 + \sqrt{y}$$ です。
240
+
241
+ 出力(ディスプレイ数式モード):
242
+ ] これはひどい $$x^2 + \sqrt{y}$$ です。
243
+
244
+
245
+
246
+ !!! ライセンス
247
+
248
+ 配布条件はMITライセンスとします。
249
+ 詳細は、gem同梱のLICENSEでご確認ください。
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # Author:: Akira FUNAI
5
+ # Copyright:: Copyright (c) 2011 Akira FUNAI
6
+
7
+ require 'rubygems'
8
+ require 'fileutils'
9
+
10
+ $LOAD_PATH.unshift ::File.expand_path('../lib', ::File.dirname(__FILE__))
11
+ require 'wtex'
12
+
13
+ case ARGV.shift
14
+ when 'init'
15
+ work_name = ARGV.shift || 'my_work'
16
+ work_dir = ::File.expand_path work_name
17
+
18
+ if ::File.exists? work_dir
19
+ $stderr.puts "#{work_dir} already exists."
20
+ exit 1
21
+ else
22
+ $stderr.puts "Setting up files in #{work_dir}..."
23
+ ::FileUtils.cp_r(
24
+ ::File.expand_path('../skel',WTeX.libdir),
25
+ work_name,
26
+ :verbose => :true
27
+ )
28
+ end
29
+ when 'correct'
30
+ when 'convert'
31
+ wt = WTeX.new
32
+ src = nil
33
+ ::File.open('./body.txt', 'r') {|f|
34
+ f.flock ::File::LOCK_SH
35
+ src = f.read
36
+ f.flock ::File::LOCK_UN
37
+ }
38
+
39
+ tex = wt.tex src
40
+ ::File.open('./body.tex', 'a') {|f|
41
+ f.flock ::File::LOCK_EX
42
+ f.seek 0
43
+ f.truncate 0
44
+ f << tex
45
+ f.flock ::File::LOCK_UN
46
+ }
47
+ else
48
+ $stderr.puts 'Usage: wikitex {init NAME|correct|convert}'
49
+ exit 1
50
+ end
@@ -0,0 +1,271 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # Author:: Akira FUNAI
5
+ # Copyright:: Copyright (c) 2011 Akira FUNAI
6
+
7
+ require 'strscan'
8
+
9
+ class WTeX
10
+
11
+ module Characters
12
+ SPECIAL_MAP = {
13
+ '#' => '\\#{}',
14
+ '%' => '\\%{}',
15
+ '&' => '\\&{}',
16
+ '_' => '\\_{}',
17
+ '<' => '\\textless{}',
18
+ '>' => '\\textgreater{}',
19
+ '^' => '\\textasciitilde{}',
20
+ '|' => '\\textbar{}',
21
+ '~' => '\\textasciicircum{}',
22
+ }
23
+ SPECIAL = SPECIAL_MAP.keys.join
24
+ WITHOUT_RUBY = '\s||ぁ-んゝゞ 、。,.?!´`/∥…‥‘’“”()〔〕[]{}〈〉《》「」『』【】♪'
25
+ end
26
+
27
+ def self.libdir
28
+ ::File.dirname __FILE__
29
+ end
30
+
31
+ def tex(str)
32
+ _tex str
33
+ end
34
+
35
+ private
36
+
37
+ def _tex(str)
38
+ tex = ''
39
+ body = ''
40
+ line = ''
41
+ type = :blank
42
+
43
+ markups = []
44
+ rex_line = /(.*?)(\\|\$\$?|\{|\n|\z)/
45
+ s = StringScanner.new str
46
+
47
+ while !s.eos? && s.scan(rex_line)
48
+ line += s[1]
49
+
50
+ if s[2] =~ /\\|\$|\{/
51
+ line += skip_tex_markup(s, s[2], markups)
52
+ next unless s.match? /\z/
53
+ end
54
+
55
+ new_type = wiki_type(line, s)
56
+
57
+ if (new_type != type) || single_line?(type)
58
+ tex += __send__("element_#{type}", body.to_s)
59
+ body = ''
60
+ end
61
+
62
+ body << line << "\n"
63
+ type = new_type
64
+ line = ''
65
+ end
66
+
67
+ tex += __send__("element_#{type}", body.to_s)
68
+ tex.gsub(/\x00(\d+)/) { markups[$1.to_i] }
69
+ end
70
+
71
+ def skip_tex_markup(s, type, markups)
72
+ if type == '\\'
73
+ if s.scan /begin\{(.+?)\}/
74
+ markups << scan_inner_contents(s, "\\begin{#{s[1]}}", "\\end{#{s[1]}}")
75
+ elsif s.scan /verb/
76
+ markups << (s.scan(/(.).*?\1/) ? "\\verb#{s[0]}" : '$\backslash$verb')
77
+ elsif s.scan /.\w*/
78
+ markups << ('\\' + s[0]) # command or escaped character
79
+ end
80
+ elsif type == '$$'
81
+ markups << (s.scan(%r/.*?[^\\]\$\$|\$\$/m) ? "$$#{s[0]}" : '\\${}\\${}')
82
+ elsif type == '$'
83
+ markups << (s.scan(%r/.*?[^\\]\$|\$/m) ? "$#{s[0]}" : '\\${}')
84
+ elsif type == '{'
85
+ markups << scan_inner_contents(s, '{', '}')
86
+ else
87
+ return '???'
88
+ end
89
+ "\x00#{markups.size - 1}"
90
+ end
91
+
92
+ def scan_inner_contents(s, open_tag, close_tag)
93
+ contents = ''
94
+ rex = /(.*?)(\\?#{Regexp.quote(open_tag)}|\\?#{Regexp.quote(close_tag)}|\z)/m
95
+ gen = 1
96
+ until s.eos? || (gen < 1)
97
+ contents << s.scan(rex)
98
+ gen += 1 if s[2] == open_tag
99
+ gen -= 1 if s[2] == close_tag
100
+ end
101
+ open_tag + contents
102
+ end
103
+
104
+ def wiki_type(line, s)
105
+ case line
106
+ when /^!/
107
+ :heading
108
+ when /^\]/
109
+ :box
110
+ when /^\|/
111
+ :code
112
+ when /^>/
113
+ :quote
114
+ when /^\*[\*\+]*\s/
115
+ :itemize
116
+ when /^\+[\*\+]*\s/
117
+ :enumerate
118
+ when /^---+$/
119
+ :separator
120
+ when /^$/
121
+ :blank
122
+ when /:$/
123
+ if s.match? /^\]/
124
+ :box
125
+ elsif s.match? /^\|/
126
+ :code
127
+ else
128
+ :p
129
+ end
130
+ else
131
+ :p
132
+ end
133
+ end
134
+
135
+ def single_line?(type)
136
+ [:heading, :newpage].include? type
137
+ end
138
+
139
+ def element_heading(body)
140
+ body.chomp!
141
+ body.gsub!(/(!+)(\*?)\s*/, '')
142
+ case $1
143
+ when '!'
144
+ "\\subsection#{$2}{#{body}}\n"
145
+ when '!!'
146
+ "\\section#{$2}{#{body}}\n"
147
+ else
148
+ "\\chapter#{$2}{#{body}}\n"
149
+ end
150
+ end
151
+
152
+ def element_box(body)
153
+ _box(body, :box)
154
+ end
155
+
156
+ def element_code(body)
157
+ _box(body, :code)
158
+ end
159
+
160
+ def _box(body, type = :box)
161
+ if body.gsub!(/\A([^\]\|].*):\n/, '')
162
+ title = escape_specials $1
163
+ end
164
+ body.gsub!(/^(\]|\|)/m, '')
165
+ body = element_p(body) if type == :box
166
+ if title
167
+ <<_eos
168
+ \\begin{WT#{type}}{#{title}}
169
+ #{body}\\end{WT#{type}}
170
+ _eos
171
+ else
172
+ <<_eos
173
+ \\begin{WT#{type}-without-title}
174
+ #{body}\\end{WT#{type}-without-title}
175
+ _eos
176
+ end
177
+ end
178
+
179
+ def element_quote(body)
180
+ body.gsub!(/^>/m, '')
181
+ <<_eos
182
+ \\begin{quote}
183
+ #{element_p body}\\end{quote}
184
+ _eos
185
+ end
186
+
187
+ def element_itemize(body)
188
+ _list(body, 'itemize')
189
+ end
190
+
191
+ def element_enumerate(body)
192
+ _list(body, 'enumerate')
193
+ end
194
+
195
+ def _list(body, item_enum)
196
+ items = []
197
+ lines = []
198
+ type = nil
199
+ (body + "\n\n").each_line {|line|
200
+ line.sub!(/^(\*|\+)/, '')
201
+
202
+ unless line =~ /^(\*|\+)/ || lines.empty?
203
+ item = inline lines.shift.to_s.chomp
204
+ unless lines.empty?
205
+ lines = lines.join
206
+ item += (lines =~ /\A\*/) ? element_itemize(lines) : element_enumerate(lines)
207
+ end
208
+ items << "\\item#{item}\n" if item != ''
209
+ lines = []
210
+ end
211
+
212
+ lines << line
213
+ }
214
+
215
+ <<_eos
216
+ \\begin{#{item_enum}}
217
+ #{items.join}\\end{#{item_enum}}
218
+ _eos
219
+ end
220
+
221
+ def element_separator(body)
222
+ "\\WTseparator{}\n"
223
+ end
224
+
225
+ def element_p(body)
226
+ body.gsub!(/\n*\Z/, '')
227
+ body.gsub!(/\n/, "\\\\\\\\\n")
228
+ "#{inline body}\n"
229
+ end
230
+
231
+ def element_blank(body)
232
+ body
233
+ end
234
+
235
+ def inline(body)
236
+ body = convert_ruby body
237
+ body = convert_strong body
238
+ body = convert_underline body
239
+ body = escape_specials body
240
+ end
241
+
242
+ def convert_ruby(body)
243
+ body.gsub!(/[|\|]?([^#{Characters::WITHOUT_RUBY}]+)《(.+?)》/u, '\\\\ruby{\\1}{\\2}')
244
+ body
245
+ end
246
+
247
+ def convert_strong(body)
248
+ body.gsub!(/(\*{2,})(.*?)\1/) {
249
+ case $1
250
+ when '**'
251
+ "{\\large\\bf #{$2}}"
252
+ when '***'
253
+ "{\\LARGE\\bf #{$2}}"
254
+ else
255
+ "{\\Huge\\bf #{$2}}"
256
+ end
257
+ }
258
+ body
259
+ end
260
+
261
+ def convert_underline(body)
262
+ body.gsub!(/__(.*?)__/, '\\WTunderline{\1}')
263
+ body
264
+ end
265
+
266
+ def escape_specials(body)
267
+ body.gsub!(/[#{Characters::SPECIAL}]/) { Characters::SPECIAL_MAP[$&] }
268
+ body
269
+ end
270
+
271
+ end