2021/FEB/23
更新履歴
目次
このページ自身も index.txt から本ツールで生成してます。
$ ./to_html.py head.yaml index.txt ezmd > index.html
ダウンロード用のスクリプト dl.py
$ chmod +x dl.py $ ./dl.py
dl.pyのバグをなおしました (2020/FEB/17)
以前に 簡易なHTMLパーサ 2018秋 を作成しました。
以降、HTML形式のものを作るときは、まずYAML形式で作成。
それから自作のツールezhtml.pyを使って、YAML形式からHTML形式に変換するようになりました。
ですがここにきて、YAML形式の作成も「かったるく」なってしまいました。
例えば、次のような既存のテキストの場合
foo.txt
Python2とPython3での日本語文字列対応について
毎回、同じようにつまづいて、同じような感じで対応してます。
なので、いいかげん自分に判りやすいようにまとめておきます。
日本語対応といっても、ソースコード中に日本語を書くつもりはありません。
データはYAML形式のファイルで用意。
そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。
結論
日本語を含む文字列処理で .foramt() や .join() を使いたい
Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。
Python3 では日本語の有無に関係なく、素直にstrのままでよし。
日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい
Python2 では素直に sys.stdin/sys.stdout を read/write。
Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。
Python2 の世界には .buffer は存在しないので注意。
まずはYAML形式で
foo.yaml
html:
- head:
- meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp": /
- title: py23str
- style: 'pre{ background: lightgray; }'
- style: 'img{ max-width: 100%; height: auto; }'
- style: 'h3{ border-left: solid gray; padding: 1em 0.5em; }'
- body:
- h1: Python2とPython3での日本語文字列対応について
- p:
- 毎回、同じようにつまづいて、同じような感じで対応してます。
- p:
- なので、いいかげん自分に判りやすいようにまとめておきます。
- p:
- 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。
- p:
- データはYAML形式のファイルで用意。
- p:
- そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
- 毎回「うぅっ」とうなってます。
- h2: 結論
- h3: 日本語を含む文字列処理で .foramt() や .join() を使いたい
- p:
- Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。
- p:
- Python3 では日本語の有無に関係なく、素直にstrのままでよし。
- h3: 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい
- p:
- Python2 では素直に sys.stdin/sys.stdout を read/write。
- p:
- Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。
- p:
- Python2 の世界には .buffer は存在しないので注意。
を作成しておいて
$ ./ezhtml.py y < foo.yaml | nkf -j > foo.html $ nkf -g foo.html ISO-2022-JP $ cat foo.html | nkf -u <html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp"> <title>py23str</title> <style>pre{ background: lightgray; }</style> <style>img{ max-width: 100%; height: auto; }</style> <style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head> <body><h1>Python2とPython3での日本語文字列対応について</h1> <p>毎回、同じようにつまづいて、同じような感じで対応してます。</p> <p>なので、いいかげん自分に判りやすいようにまとめておきます。</p> <p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p> <p>データはYAML形式のファイルで用意。</p> <p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。</p> <h2>結論</h2> <h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3> <p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p> <p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p> <h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3> <p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p> <p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p> <p>Python2 の世界には .buffer は存在しないので注意。</p></body></html>
に変換。
foo.html
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head>
<body><h1>Python2とPython3での日本語文字列対応について</h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。</p>
<h2>結論</h2>
<h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので注意。</p></body></html>
このように表示されます。
ですが、このYAML形式を作成するのが結構ツライです。
できれば foo.txt から foo.yaml の形式に変換できないものか...
世の中にはマークダウン形式の規格・仕様は存在します。
ですが、ここはひとつ目をつむって「簡易おれおれマークダウン」な仕様の 変換ツールを作ってみる事にします。
foo.yaml の段階で、headとbodyに分かれてます。
そしてbody以降は、最低スペース2つの字下げが必ず入ってます。
headでfoo.txtからの固有の情報は
- title: py23str
だけで、あとはほぼお決まりで固定です。
headのtilteはあとで編集するとして、bodyだけ何とか変換するように目指してみます。
まずは
foo_head.yaml
- meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp": /
- title: py23str
- style: 'pre{ background: lightgray; }'
- style: 'img{ max-width: 100%; height: auto; }'
- style: 'h3{ border-left: solid gray; padding: 1em 0.5em; }'
を用意。
そして
foo.txt
Python2とPython3での日本語文字列対応について
毎回、同じようにつまづいて、同じような感じで対応してます。
なので、いいかげん自分に判りやすいようにまとめておきます。
日本語対応といっても、ソースコード中に日本語を書くつもりはありません。
データはYAML形式のファイルで用意。
そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。
結論
日本語を含む文字列処理で .foramt() や .join() を使いたい
Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。
Python3 では日本語の有無に関係なく、素直にstrのままでよし。
日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい
Python2 では素直に sys.stdin/sys.stdout を read/write。
Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。
Python2 の世界には .buffer は存在しないので注意。
Python2とPython3での日本語文字列対応について
毎回、同じようにつまづいて、同じような感じで対応してます。
なので、いいかげん自分に判りやすいようにまとめておきます。
日本語対応といっても、ソースコード中に日本語を書くつもりはありません。
データはYAML形式のファイルで用意。
そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。
結論
日本語を含む文字列処理で .foramt() や .join() を使いたい
Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。
Python3 では日本語の有無に関係なく、素直にstrのままでよし。
日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい
Python2 では素直に sys.stdin/sys.stdout を read/write。
Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。
Python2 の世界には .buffer は存在しないので注意。
から、これから作成を目指すツールで、何とか
foo_body.yaml
- h1: Python2とPython3での日本語文字列対応について
- p:
- 毎回、同じようにつまづいて、同じような感じで対応してます。
- p:
- なので、いいかげん自分に判りやすいようにまとめておきます。
- p:
- 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。
- p:
- データはYAML形式のファイルで用意。
- p:
- そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
- 毎回「うぅっ」とうなってます。
- h2: 結論
- h3: 日本語を含む文字列処理で .foramt() や .join() を使いたい
- p:
- Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。
- p:
- Python3 では日本語の有無に関係なく、素直にstrのままでよし。
- h3: 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい
- p:
- Python2 では素直に sys.stdin/sys.stdout を read/write。
- p:
- Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。
- p:
- Python2 の世界には .buffer は存在しないので注意。
を自動生成します。
あとはスクリプトなり何なりで、例えば
$ ( echo '<html><head>' ; ./ezhtml.py y < foo_head.yaml ; echo '</head><body>' ; ./ezhtml.py y < foo_body.yaml ; echo '</body></html>' ) | nkf -j > foo2.html $ nkf -g foo2.html ISO-2022-JP $ nkf -u foo2.html <html><head> <meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp"> <title>py23str</title> <style>pre{ background: lightgray; }</style> <style>img{ max-width: 100%; height: auto; }</style> <style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style> </head><body> <h1>Python2とPython3での日本語文字列対応について</h1> <p>毎回、同じようにつまづいて、同じような感じで対応してます。</p> <p>なので、いいかげん自分に判りやすいようにまとめておきます。</p> <p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p> <p>データはYAML形式のファイルで用意。</p> <p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。</p> <h2>結論</h2> <h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3> <p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p> <p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p> <h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3> <p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p> <p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p> <p>Python2 の世界には .buffer は存在しないので注意。</p> </body></html>
foo2.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1>Python2とPython3での日本語文字列対応について</h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。</p>
<h2>結論</h2>
<h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので注意。</p>
</body></html>
となります。
おれおれ仕様のツールなので、 自分がよく使うHTMLのタグだけ対応して、 滅多に使わないものは、最後に手動で編集する事にします。
HTMLのbodyの中で、自分がよく使うタグは何か?
とりあえず、このくらい。
最初はここから foo.txt の範囲だけに絞って
だけで骨組みを考えてみます。
foo.txt から foo_body.yaml を生成したい訳ですが、 テキストを、属してるタグで切り分けてみると
;;; --> h1 Python2とPython3での日本語文字列対応について ;;; <-- h1 ;;; --> p 毎回、同じようにつまづいて、同じような感じで対応してます。 なので、いいかげん自分に判りやすいようにまとめておきます。 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 データはYAML形式のファイルで用意。 そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。 ;;; <-- p ;;; --> h2 結論 ;;; <-- h2 ;;; --> h3 日本語を含む文字列処理で .foramt() や .join() を使いたい ;;; <-- h3 ;;; --> p Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 Python3 では日本語の有無に関係なく、素直にstrのままでよし。 ;;; <-- p ;;; --> h3 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい ;;; <-- h3 ;;; --> p Python2 では素直に sys.stdin/sys.stdout を read/write。 Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 Python2 の世界には .buffer は存在しないので注意。 ;;; <-- p
HTML形式だと、開始タグと終了タグで、まさにこのような感じで領域を指示します。
おれおれマークダウンでは、簡易な記述を目指すので、モード(状態)を持たせます。
テキストの先頭から末尾に向かって、状態を切り替えて、どのタグの領域かを指示する事にします。
例えば、次のように。
h1 Python2とPython3での日本語文字列対応について p 毎回、同じようにつまづいて、同じような感じで対応してます。 なので、いいかげん自分に判りやすいようにまとめておきます。 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 データはYAML形式のファイルで用意。 そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。 h2 結論 h3 日本語を含む文字列処理で .foramt() や .join() を使いたい p Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 Python3 では日本語の有無に関係なく、素直にstrのままでよし。 h3 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい p Python2 では素直に sys.stdin/sys.stdout を read/write。 Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 Python2 の世界には .buffer は存在しないので注意。
p, h1, h2, h3をモード名として、モード名だけの行が現れると、 現在のモードをそのモードに切り替えます。
他のモードに切り替わるまでの間の複数行のテキストについて
h1 Python2とPython3での日本語文字列対応について p
は
- h1: Python2とPython3での日本語文字列対応について
てな具合に。
他のモードに切り替わるまでの間の複数行のテキストについて
p 毎回、同じようにつまづいて、同じような感じで対応してます。 なので、いいかげん自分に判りやすいようにまとめておきます。 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 データはYAML形式のファイルで用意。 そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。 h2
は
- p: - 毎回、同じようにつまづいて、同じような感じで対応してます。 - p: - なので、いいかげん自分に判りやすいようにまとめておきます。 - p: - 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 - p: - データはYAML形式のファイルで用意。 - p: - そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 - 毎回「うぅっ」とうなってます。
てな具合に。
ではこの仕様で、骨組みのコーディング。
$ cat ezmd.py #!/usr/bin/env python import yaml import nkf heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ] end = '$$$_end_$$$' modes = heads + [ 'p', end ] def do_mode(mode, buf, res): if mode in heads: buf = list( map( lambda s: s.strip(), buf ) ) buf = list( filter( lambda s: s!='', buf ) ) s = ''.join(buf) res.append( { mode: s } ) elif mode == 'p': buf = list( map( lambda s: s.strip(), buf ) ) buf.append('') (lsts, lst) = ( [], [] ) for s in buf: if s: lst.append(s) elif lst: lsts.append(lst) lst = [] for lst in lsts: res.append( { 'p': lst } ) def ezmd(lst): lst = ['p'] + lst + [end] (buf, res) = ( [], [] ) mode = '' while mode != end: s = lst.pop(0) if s in modes and s != mode: do_mode(mode, buf, res) mode = s buf = [] else: buf.append(s) return res if __name__ == "__main__": b = nkf.get_stdin() (s, nkf_opt) = nkf.to_str(b) lst = s.split('\n') lst = ezmd(lst) u8 = yaml.dump( lst, default_flow_style=False, allow_unicode=True, encoding='utf-8' ) b = nkf.cvt(u8, nkf_opt) if nkf_opt != '-u' else u8 nkf.put_stdout(b) # EOF
日本語の文字コードの問題やPython2, Python3の問題は、すべて nkf.py が吸収してくれてるはずと信じて、進めてみます。
ezhtml.py
#!/usr/bin/env python
import sys
import yaml
import six
import nkf
import cmd_ut
def cv_amp(s, d='enc'):
lst = [ ('&','&'), ('<','<'), ('>','>') ]
if d != 'enc':
lst = reversed(lst)
for (f, t) in lst:
if d != 'enc':
(f, t) = (t, f)
s = s.replace(f, t)
return s
def dump_tag(tag, v, pre):
if tag == '!--':
return '<!--' + v + '-->'
lst = bak = tag.split(' ')
if lst[-1] == '/':
lst = lst[:-1]
if lst[0][-1] == '/':
lst = [ lst[0][:-1] ] + lst[1:]
t = 'bare="True"'
bare = t in lst
if bare:
lst.remove(t)
if t in bak:
bak.remove(t)
s = '<' + ' '.join(lst) + '>'
if v != '/':
s += html_dump( v, lst[0].lower() == 'pre', bare=bare )
if lst == bak:
s += '</' + lst[0] + '>'
return s
def get_tag_v(d):
return list( d.items() )[0]
def html_dump(o, pre=False, bare=False):
if not o:
return ''
if type(o) == list:
delim = '' if pre else '\n'
return delim.join( map( lambda e: html_dump(e, pre), o ) )
if type(o) == dict:
(tag, v) = get_tag_v(o)
return dump_tag(tag, v, pre)
return o if bare else cv_amp(o)
def get_tag(s):
(p, tag) = ('', [])
while '<' in s:
i = s.index('<')
(t, s) = ( s[:i], s[i+1:] )
p += t
if s[:3] == '!--' and '-->' in s[3:]:
tag.append('!--')
s = s[3:]
i = s.index('-->')
tag.append( s[:i] )
s = s[i+3:]
break
tag.append('<')
n = s[:1]
if n == '/':
tag.append('/')
s = s[1:]
n = s[:1]
if n.isalpha():
if '>' not in s:
err( "not found '>'", 'tag={}'.format(tag) )
i = s.index('>')
tag = tag[1:] + s[:i].split(' ')
s = s[i+1:]
break
p += ''.join(tag)
tag = []
if not tag:
(p, s) = (p+s, '')
return (p, tag, s)
def start_idx(stk, s):
for i in reversed( range( len(stk) ) ):
e = stk[i]
if type(e) == list and e[0] == s:
return i
return -1
def solo_tag(e):
if type(e) == list:
if e[0] == '!--':
return { '!--': e[1] }
(h, e) = ( '/', e[1:] ) if e[0] == '/' else ('', e)
return { h + ' '.join(e): '/' }
return e
def is_solo_tag_has_v(e):
lst = ['li']
if type(e) != dict:
return False
(tag, v) = get_tag_v(e)
return v == '/' and tag.split(' ')[0] in lst
def solo_tag_has_v_idx(lst):
for i in range( len(lst) ):
if is_solo_tag_has_v( lst[i] ):
return i
return -1
def strip_lst1(o):
while type(o) == list and len(o) == 1:
o = o[0]
return o
def solo_tags_modify(lst):
def div_lst(lst):
i = solo_tag_has_v_idx(lst)
return ( lst[:i], lst[i:] ) if i >= 0 else ( lst, [] )
r = []
while lst:
(p, lst) = div_lst(lst)
r += p
if lst:
(e, lst) = ( lst[0], lst[1:] )
(tag, v) = get_tag_v(e) # v == '/'
(p, lst) = div_lst(lst)
r += [ { tag + ' /': strip_lst1(p) } ]
return r
def solo_tags(lst):
return list( map( solo_tag, lst ) )
def untabify(s, n=8):
def f(s):
r = ''
for c in s:
if c == '\t':
c = ' ' * ( n - len(r) % n )
r += c
return r
lst = s.split('\n')
lst = map(f, lst)
return '\n'.join(lst)
def strip_lst(lst, pre):
def f(e):
if type(e) == dict:
return e
if pre:
while ' \n' in e:
e = e.replace(' \n', '\n')
return untabify(e)
return e.replace('\n', ' ').strip()
return list( filter( lambda e: e != '', map(f, lst) ) )
def close_solo_tag(lst, pre=False):
lst = solo_tags(lst)
lst = strip_lst(lst, pre)
lst = solo_tags_modify(lst)
return lst
def close_tag(lst, pre):
(tag, lst) = ( lst[0], lst[1:] )
lst = close_solo_tag(lst, pre)
v = lst
if len(lst) == 1:
v = lst[0]
elif not lst:
v = ''
return { ' '.join(tag): v }
def html_load(s):
stk = []
pre_cnt = 0
def add_cnt(tag):
pre = ( tag[1] if tag[0] == '/' else tag[0] ).lower() == 'pre'
return ( -1 if tag[0] == '/' else 1 ) if pre else 0
while True:
(p, tag, s) = get_tag(s)
if not tag:
break
if p:
stk.append( cv_amp(p, 'dec') )
if tag[0] != '/':
stk.append(tag)
pre_cnt += add_cnt(tag)
continue
i = start_idx( stk, tag[1] )
if i >= 0:
stk = stk[:i] + [ close_tag( stk[i:], pre_cnt > 0 ) ]
pre_cnt += add_cnt(tag)
else:
stk.append( solo_tag(tag) )
o = close_solo_tag( stk, pre_cnt > 0 )
return strip_lst1(o)
def yaml_dump(o):
def represent_str(dumper, instance):
tag = 'tag:yaml.org,2002:str'
style = '|' if '\n' in instance else None
return dumper.represent_scalar( tag, instance, style=style )
for typ in [ str ] + ( [ unicode ] if six.PY2 else [] ):
yaml.add_representer(typ, represent_str)
u8 = yaml.dump( o, default_flow_style=False, allow_unicode=True, encoding='utf-8' )
return nkf.dec(u8)
if __name__ == "__main__":
b = nkf.get_stdin()
opt = nkf.guess(b)
is_html = lambda : nkf.dec( cmd_ut.call_comm('file - | grep -i html', b) ).strip()
html = True if 'h' in sys.argv else False if 'y' in sys.argv else is_html()
u8 = nkf.cvt(b, '-u')
s = nkf.dec(u8)
if html:
o = html_load(s)
s = yaml_dump(o)
else:
o = yaml.load(s)
s = html_dump(o) + '\n'
u8 = nkf.enc(s)
b = nkf.cvt(u8, opt)
nkf.put_stdout(b)
# EOF
nkf.py は使いまわしつつ、互換性を保ちながらアップデートしてきたので、
テキスト配置ツール
から最新版の
を配置しておきます。
おれおれ仕様のテキストファイルは
foo2.txt
h1
Python2とPython3での日本語文字列対応について
p
毎回、同じようにつまづいて、同じような感じで対応してます。
なので、いいかげん自分に判りやすいようにまとめておきます。
日本語対応といっても、ソースコード中に日本語を書くつもりはありません。
データはYAML形式のファイルで用意。
そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。
h2
結論
h3
日本語を含む文字列処理で .foramt() や .join() を使いたい
p
Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。
Python3 では日本語の有無に関係なく、素直にstrのままでよし。
h3
日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい
p
Python2 では素直に sys.stdin/sys.stdout を read/write。
Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。
Python2 の世界には .buffer は存在しないので注意。
それでは実行。
$ ./ezmd.py < foo2.txt - h1: Python2とPython3での日本語文字列対応について - p: - 毎回、同じようにつまづいて、同じような感じで対応してます。 - p: - なので、いいかげん自分に判りやすいようにまとめておきます。 - p: - 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 - p: - データはYAML形式のファイルで用意。 - p: - そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 - 毎回「うぅっ」とうなってます。 - h2: 結論 - h3: 日本語を含む文字列処理で .foramt() や .join() を使いたい - p: - Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 - p: - Python3 では日本語の有無に関係なく、素直にstrのままでよし。 - h3: 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - p: - Python2 では素直に sys.stdin/sys.stdout を read/write。 - p: - Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 - p: - Python2 の世界には .buffer は存在しないので注意。
出力されたHTML形式をさらにezhtml.pyにつないでHTML形式に。
$ ./ezmd.py < foo2.txt | ./ezhtml.py <h1>Python2とPython3での日本語文字列対応について</h1> <p>毎回、同じようにつまづいて、同じような感じで対応してます。</p> <p>なので、いいかげん自分に判りやすいようにまとめておきます。</p> <p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p> <p>データはYAML形式のファイルで用意。</p> <p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。</p> <h2>結論</h2> <h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3> <p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p> <p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p> <h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3> <p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p> <p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p> <p>Python2 の世界には .buffer は存在しないので注意。</p>
大丈夫そうですね。 headとつなげて仕上げを。
仕上げ用のツールを用意しときます。
to_html.py
#!/usr/bin/env python
import sys
import arg
import cmd_ut
cmd_py = cmd_ut.cmd_py
add_opt = lambda opt, v: ( opt + ' ' if v else '' ) + v
if __name__ == "__main__":
a = arg.new()
title = a.pop_str('-t')
title = add_opt( '-t', title )
head = a.pop_str( '-h', 'head.yaml' )
head = add_opt( '-h', head )
out = a.pop_str('-o', 'index.html')
body = a.pop('index.txt')
if not title:
cmd = '{} < {}'.format( cmd_py( 'get_title' ), body )
title = cmd_ut.call( cmd, b2s=True )
if title:
title = "'{}'".format( title )
title = add_opt( '-t', title )
ezhtml = cmd_py( 'ezhtml' ) + ' y'
if out.endswith( '.yaml' ) or a.is_pop( '-yaml' ):
ezhtml = 'cat'
if out != '-':
ezhtml += ' > ' + out
fmt = '{} < {} | {} {} {} | {}'
cmd = fmt.format( cmd_py('ezmd'), body, cmd_py('join_yaml'), title, head, ezhtml )
s = cmd_ut.call(cmd)
if out == '-':
sys.stdout.write( s.decode() )
# EOF
foo3.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1>Python2とPython3での日本語文字列対応について</h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。</p>
<h2>結論</h2>
<h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので注意。</p>
</body></html>
OK。
todo
追加してみます。
preタグの場合、どこまでがpreタグの中か? 次のモードへの切り替えの判定が微妙です。
このモードは特別に、'/'だけの行でモード終了としてみます。
行頭に'/'だけ表示したい事はまぁ無いだろうし、 あったとしても、' ' + '/' にして行頭にスペースを入れてしのぐ事にします。
モードが終了するまでの間の複数行のテキストについて
preタグのYAMLへの変換は
簡易なHTMLパーサ 2018秋 preタグのyamlダンプ でこしらえた yaml_dump() を流用しておきます。
ezhtml.pyのオリジナルのyaml_dump()ではstrを返す仕様にしてました。 今回の場面ではUTF-8のままで良いので、そのように修正して使います。
モード終了指示の方式にすると、 '/' で終了してから、次のモードまでの滞空期間ができてしまいます。
モードが何者でもないその間は、とりあえずデフォルトのpモードで。
pモード中に何もテキストがなく、続く別のモードが始まれば、 デフォルトpモードでは何も表示しないので、大丈夫でしょう。
v2.patch
diff -ur v1/ezmd.py v2/ezmd.py
--- v1/ezmd.py 2019-09-22 11:49:17.000000000 +0900
+++ v2/ezmd.py 2019-09-23 04:47:56.000000000 +0900
@@ -1,11 +1,19 @@
#!/usr/bin/env python
import yaml
+import six
import nkf
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
end = '$$$_end_$$$'
-modes = heads + [ 'p', end ]
+modes = heads + [ 'p', 'pre', end ]
+
+def is_mode_switch(s, mode):
+ if mode == 'pre':
+ return s == '/'
+ return s in modes and s != mode
+
+next_mode = lambda s: 'p' if s == '/' else s
def do_mode(mode, buf, res):
if mode in heads:
@@ -26,20 +34,40 @@
lst = []
for lst in lsts:
res.append( { 'p': lst } )
+ elif mode == 'pre':
+ while buf and buf[0] == '':
+ buf.pop(0)
+ while buf and buf[-1] == '':
+ buf.pop()
+ if buf:
+ s = '\n'.join(buf) + '\n'
+ res.append( { 'pre': s } )
+
def ezmd(lst):
lst = ['p'] + lst + [end]
(buf, res) = ( [], [] )
mode = ''
while mode != end:
s = lst.pop(0)
- if s in modes and s != mode:
+ if is_mode_switch(s, mode):
do_mode(mode, buf, res)
- mode = s
+ mode = next_mode(s)
buf = []
- else:
+ elif s != mode:
buf.append(s)
return res
+def yaml_dump(o):
+ def represent_str(dumper, instance):
+ tag = 'tag:yaml.org,2002:str'
+ style = '|' if '\n' in instance else None
+ return dumper.represent_scalar( tag, instance, style=style )
+
+ for typ in [ str ] + ( [ unicode ] if six.PY2 else [] ):
+ yaml.add_representer(typ, represent_str)
+
+ return yaml.dump( o, default_flow_style=False, allow_unicode=True, encoding='utf-8' )
+
if __name__ == "__main__":
b = nkf.get_stdin()
(s, nkf_opt) = nkf.to_str(b)
@@ -47,7 +75,7 @@
lst = ezmd(lst)
- u8 = yaml.dump( lst, default_flow_style=False, allow_unicode=True, encoding='utf-8' )
+ u8 = yaml_dump(lst)
b = nkf.cvt(u8, nkf_opt) if nkf_opt != '-u' else u8
nkf.put_stdout(b)
# EOF
$ cat v2.patch | patch -p1
foo_2.txt
h1
Python2とPython3での日本語文字列対応について
p
毎回、同じようにつまづいて、同じような感じで対応してます。
なので、いいかげん自分に判りやすいようにまとめておきます。
日本語対応といっても、ソースコード中に日本語を書くつもりはありません。
データはYAML形式のファイルで用意。
そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。
h2
結論
h3
日本語を含む文字列処理で .foramt() や .join() を使いたい
p
Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。
Python3 では日本語の有無に関係なく、素直にstrのままでよし。
h3
日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい
p
Python2 では素直に sys.stdin/sys.stdout を read/write。
Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。
Python2 の世界には .buffer は存在しないので注意。
pre
$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
/
ここはデフォルトp
p
ここは明示的にp
pre
ここはpre
p
ここもpre
h1
ここもpre
/
p
ここはp
実行してみます。
$ ./ezmd.py < foo_2.txt - h1: Python2とPython3での日本語文字列対応について - p: - 毎回、同じようにつまづいて、同じような感じで対応してます。 - p: - なので、いいかげん自分に判りやすいようにまとめておきます。 - p: - 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 - p: - データはYAML形式のファイルで用意。 - p: - そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 - 毎回「うぅっ」とうなってます。 - h2: 結論 - h3: 日本語を含む文字列処理で .foramt() や .join() を使いたい - p: - Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 - p: - Python3 では日本語の有無に関係なく、素直にstrのままでよし。 - h3: 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - p: - Python2 では素直に sys.stdin/sys.stdout を read/write。 - p: - Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 - p: - Python2 の世界には .buffer は存在しないので注意。 - pre: | $ cat p2.py #!/usr/bin/env python2 import sys import yaml if __name__ == "__main__": s = sys.stdin.read() d = yaml.load(s) foo = d.get('foo') bar = d.get('bar') d['hoge'] = foo + ' ' + bar d['fuga'] = 'foo={} bar={}'.format(foo, bar) d['guha'] = '(^_^)'.join( d.values() ) s = yaml.dump(d, default_flow_style=False) sys.stdout.write(s) # EOF - p: - ここはデフォルトp - p: - ここは明示的にp - pre: | ここはpre p ここもpre h1 ここもpre - p: - ここはp
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_2.txt > foo_2.html
foo_2.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1>Python2とPython3での日本語文字列対応について</h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。</p>
<h2>結論</h2>
<h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので注意。</p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<p>ここはp</p>
</body></html>
todo
追加してみます。
全体の簡単にするためにモードの開始、終了をトップレベルの状態の遷移だけにしました。
なので、基本的に「入れ子」の構造を諦めてます。
が、ですが、このulモードの中だけは「入れ子」を結構使ってます。
例えば
- ul: - li /: 標準入力からYAML形式のテキストを読み込み - li /: yaml.load()でテキストをデータに - li /: データの文字列2つを - li /: ごにょごにょいじって - ul: - li /: foo + ' ' + bar - li /: .format() - li /: .join() - li /: yaml.dump()でデータをYAML形式のテキストにして - li /: 標準出力に書き出し
こうして
<ul><li>標準入力からYAML形式のテキストを読み込み <li>yaml.load()でテキストをデータに <li>データの文字列2つを <li>ごにょごにょいじって <ul><li>foo + ' ' + bar <li>.format() <li>.join()</ul> <li>yaml.dump()でデータをYAML形式のテキストにして <li>標準出力に書き出し</ul>
こうなって
このように。
ここまでのモードの関連に従うならば、 例えば上記の結果になる元のテキストは
ul 標準入力からYAML形式のテキストを読み込み yaml.load()でテキストをデータに データの文字列2つを ごにょごにょいじって foo + ' ' + bar .format() .join() yaml.dump()でデータを \ YAML形式のテキストにして 標準出力に書き出し
こうありたい。
ulモード中では、行頭の字下げの数で「入れ子」の指示になるという仕様で、 何とか考えてみました。
v3.patch
diff -ur v2/ezmd.py v3/ezmd.py
--- v2/ezmd.py 2019-09-23 04:47:56.000000000 +0900
+++ v3/ezmd.py 2019-09-24 00:19:15.000000000 +0900
@@ -5,8 +5,7 @@
import nkf
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
-end = '$$$_end_$$$'
-modes = heads + [ 'p', 'pre', end ]
+modes = heads + [ 'p', 'pre', 'ul' ]
def is_mode_switch(s, mode):
if mode == 'pre':
@@ -15,6 +14,68 @@
next_mode = lambda s: 'p' if s == '/' else s
+def strip_head(s):
+ while s and s[0] in (' ', '\t'):
+ s = s[1:]
+ return s
+
+def strip_tail(s):
+ while s and s[-1] in (' ', '\t'):
+ s = s[:-1]
+ return s
+
+def idt_cnt(s):
+ i = 0
+ while s and s[0] in (' ', '\t'):
+ i += 1
+ s = s[1:]
+ return (i, s)
+
+def esc_join(lst):
+ res = []
+ for s in lst:
+ if res and res[-1][-1] == '\\':
+ t = res[-1][:-1]
+ res[-1] = strip_tail(t) + strip_head(s)
+ else:
+ res.append(s)
+ return res
+
+def do_mode_ul(buf, res):
+ buf = esc_join(buf)
+ buf = list( filter( lambda s: s.strip(), buf ) )
+ buf = list( map(idt_cnt, buf) ) # (i, s)
+
+ (stk, lsts) = ( [], [] )
+
+ def push(i, s):
+ lst = [s]
+ ( stk[-1][1] if stk else lsts ).append(lst)
+ stk.append( (i, lst) )
+
+ def buf_to_stk_lsts(i_s):
+ (i, s) = i_s
+ if stk:
+ (ci, clst) = stk[-1]
+ if i > ci:
+ push(i, s)
+ elif i < ci:
+ stk.pop()
+ buf_to_stk_lsts(i_s)
+ else: # i == ci
+ clst.append(s)
+ else:
+ push(i, s)
+
+ list( map(buf_to_stk_lsts, buf) ) # make lists
+
+ def lst_to(lst):
+ f = lambda o: lst_to(o) if type(o) == list else {'li /': o}
+ lst = list( map(f, lst) )
+ return { 'ul': lst }
+
+ res.extend( list( map(lst_to, lsts) ) )
+
def do_mode(mode, buf, res):
if mode in heads:
buf = list( map( lambda s: s.strip(), buf ) )
@@ -42,12 +103,14 @@
if buf:
s = '\n'.join(buf) + '\n'
res.append( { 'pre': s } )
+ elif mode == 'ul':
+ do_mode_ul(buf, res)
def ezmd(lst):
- lst = ['p'] + lst + [end]
+ lst = ['p'] + lst
(buf, res) = ( [], [] )
mode = ''
- while mode != end:
+ while lst:
s = lst.pop(0)
if is_mode_switch(s, mode):
do_mode(mode, buf, res)
@@ -55,6 +118,7 @@
buf = []
elif s != mode:
buf.append(s)
+ do_mode(mode, buf, res)
return res
def yaml_dump(o):
$ cat v3.patch | patch -p1
foo_3.txt
h1
Python2とPython3での日本語文字列対応について
p
毎回、同じようにつまづいて、同じような感じで対応してます。
なので、いいかげん自分に判りやすいようにまとめておきます。
日本語対応といっても、ソースコード中に日本語を書くつもりはありません。
データはYAML形式のファイルで用意。
そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。
h2
結論
h3
日本語を含む文字列処理で .foramt() や .join() を使いたい
p
Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。
Python3 では日本語の有無に関係なく、素直にstrのままでよし。
h3
日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい
p
Python2 では素直に sys.stdin/sys.stdout を read/write。
Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。
Python2 の世界には .buffer は存在しないので注意。
pre
$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
/
ここはデフォルトp
p
ここは明示的にp
pre
ここはpre
p
ここもpre
h1
ここもpre
/
p
ここはp
ul
標準入力からYAML形式のテキストを読み込み
yaml.load()でテキストをデータに
データの文字列2つを
ごにょごにょいじって
foo + ' ' + bar
.format()
.join()
yaml.dump()でデータを \
YAML形式のテキストにして
標準出力に書き出し
pre
ここはpre
実行してみます。
$ ./ezmd.py < foo_3.txt : - p: - ここはp - ul: - li /: 標準入力からYAML形式のテキストを読み込み - li /: yaml.load()でテキストをデータに - li /: データの文字列2つを - li /: ごにょごにょいじって - ul: - li /: foo + ' ' + bar - li /: .format() - li /: .join() - li /: yaml.dump()でデータをYAML形式のテキストにして - li /: 標準出力に書き出し - pre: |2 ここはpre
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_3.txt > foo_3.html
foo_3.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1>Python2とPython3での日本語文字列対応について</h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。</p>
<h2>結論</h2>
<h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので注意。</p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<p>ここはp</p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li>データの文字列2つを
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し</ul>
<pre> ここはpre
</pre>
</body></html>
todo
追加してみます。
自分のa href="xxx"タグの使い方を振り返ると、 ほとんどpタグの中かulタグの中です。
なのでとりあえず、pモードとulモードの文字列処理の箇所だけに、対応を入れてみます。
a (href)の場合、トップレベルのモードを遷移させるまでもなさそうです。
文字列中に [[ xxx | yyy ]] の記載があれば YAML形式の - a href="xxx": yyy を経て HTML形式で <a href="xxx"> yyy </a> に 文字列中に [[ xxx ]] の記載があれば YAML形式の - a href="xxx": xxx } を経て HTML形式で <a href="xxx"> xxx </a> に
このくらいの仕様でやってみます。
v4.patch
diff -ur v3/ezmd.py v4/ezmd.py
--- v3/ezmd.py 2019-09-24 00:19:15.000000000 +0900
+++ v4/ezmd.py 2019-09-25 00:23:47.000000000 +0900
@@ -14,6 +14,8 @@
next_mode = lambda s: 'p' if s == '/' else s
+lst_strip = lambda lst: list( map( lambda s: s.strip(), lst ) )
+
def strip_head(s):
while s and s[0] in (' ', '\t'):
s = s[1:]
@@ -41,6 +43,22 @@
res.append(s)
return res
+s_idx = lambda s, p, dv=-1: s.index(p) if p in s else dv
+
+def do_str(s):
+ # a href
+ (h, t) = ('[[', ']]')
+ (ih, it) = list( map( lambda p: s_idx(s, p), (h, t) ) )
+ if 0 <= ih and ih < it:
+ s3 = lst_strip( ( s[:ih], s[ih+len(h):it], s[it+len(t):] ) )
+ m = s3[1]
+ if m:
+ (href, v) = lst_strip( m.split('|') ) if '|' in m else (m, m)
+ s3[1] = { 'a href="{}"'.format(href): v } if href else v
+ lst = list( filter( lambda o: o, s3 ) )
+ return lst[0] if len(lst) == 1 else lst
+ return s
+
def do_mode_ul(buf, res):
buf = esc_join(buf)
buf = list( filter( lambda s: s.strip(), buf ) )
@@ -70,7 +88,7 @@
list( map(buf_to_stk_lsts, buf) ) # make lists
def lst_to(lst):
- f = lambda o: lst_to(o) if type(o) == list else {'li /': o}
+ f = lambda o: lst_to(o) if type(o) == list else {'li /': do_str(o) }
lst = list( map(f, lst) )
return { 'ul': lst }
@@ -78,12 +96,12 @@
def do_mode(mode, buf, res):
if mode in heads:
- buf = list( map( lambda s: s.strip(), buf ) )
+ buf = lst_strip(buf)
buf = list( filter( lambda s: s!='', buf ) )
s = ''.join(buf)
res.append( { mode: s } )
elif mode == 'p':
- buf = list( map( lambda s: s.strip(), buf ) )
+ buf = lst_strip(buf)
buf.append('')
(lsts, lst) = ( [], [] )
@@ -94,6 +112,8 @@
lsts.append(lst)
lst = []
for lst in lsts:
+ to_lst = lambda o: o if type(o) == list else [o]
+ lst = sum( map( lambda s: to_lst( do_str(s) ), lst ), [] )
res.append( { 'p': lst } )
elif mode == 'pre':
while buf and buf[0] == '':
$ cat v4.patch | patch -p1
foo_4.txt
h1
Python2とPython3での日本語文字列対応について
p
毎回、同じようにつまづいて、同じような感じで対応してます。
なので、いいかげん自分に判りやすいようにまとめておきます。
日本語対応といっても、ソースコード中に日本語を書くつもりはありません。
データはYAML形式のファイルで用意。
そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。
h2
結論
h3
日本語を含む文字列処理で .foramt() や .join() を使いたい
p
Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。
Python3 では日本語の有無に関係なく、素直にstrのままでよし。
h3
日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい
p
Python2 では素直に sys.stdin/sys.stdout を read/write。
Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。
Python2 の世界には .buffer は存在しないので注意。
pre
$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
/
ここはデフォルトp
p
ここは明示的にp
[[v2.patch]]
バージョン2のための[[ v2.patch | パッチ ]] となります。
[[http://kondoh.html.xdomain.jp/ezhtml/index.html | 簡易なHTMLパーサ 2018秋]]
これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。
pre
ここはpre
p
ここもpre
h1
ここもpre
/
ul
[[v2.patch]]
[[v3.patch]]
バージョン2のための[[ v2.patch | パッチ ]] となります。
これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。
p
ここはp
ul
標準入力からYAML形式のテキストを読み込み
yaml.load()でテキストをデータに
データの文字列2つを
ごにょごにょいじって
foo + ' ' + bar
.format()
.join()
yaml.dump()でデータを \
YAML形式のテキストにして
標準出力に書き出し
pre
ここはpre
実行してみます。
$ ./ezmd.py < foo_4.txt : - p: - ここは明示的にp - p: - a href="v2.patch": v2.patch - p: - バージョン2のための - a href="v2.patch": パッチ - となります。 - p: - a href="http://kondoh.html.xdomain.jp/ezhtml/index.html": 簡易なHTMLパーサ 2018秋 - p: - これは - a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import": pythonのモジュールのインポート - について。 - pre: | ここはpre p ここもpre h1 ここもpre - ul: - li /: a href="v2.patch": v2.patch - li /: a href="v3.patch": v3.patch - li /: - バージョン2のための - a href="v2.patch": パッチ - となります。 - li /: - これは - a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import": pythonのモジュールのインポート - について。 - p: - ここはp
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_4.txt > foo_4.html
foo_4.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1>Python2とPython3での日本語文字列対応について</h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。</p>
<h2>結論</h2>
<h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので注意。</p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<p><a href="v2.patch">v2.patch</a></p>
<p>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。</p>
<p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p>
<p>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。
<li>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</ul>
<p>ここはp</p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li>データの文字列2つを
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し</ul>
<pre> ここはpre
</pre>
</body></html>
todo
追加してみます。
複数のハイフンだけの行が現れると、横線に変換する事にしてみます。
ハイフン2つだけとかなら他に何か意味ありそうなので、 一応4個以上の場合に有効とします。
自分のhrタグの使用箇所は、そのほとんどが
- p: { hr: / }
経ての
<p><hr></p>
として使ってます。
ハイフン4個以上の行が複数行続く場合も、その行数の横線になるように。
横線指示の直後にモード指定が無い場合は、 デフォルトのモード'p'として扱う事にします。
v5.patch
diff -ur v4/ezmd.py v5/ezmd.py
--- v4/ezmd.py 2019-09-25 00:23:47.000000000 +0900
+++ v5/ezmd.py 2019-09-26 21:40:15.000000000 +0900
@@ -7,12 +7,24 @@
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
modes = heads + [ 'p', 'pre', 'ul' ]
-def is_mode_switch(s, mode):
+is_all_ge_n = lambda s, c, n: all( map( lambda c_: c_ == c, s ) ) and len(s) >= n
+
+def next_mode_switch(s, mode):
if mode == 'pre':
- return s == '/'
- return s in modes and s != mode
+ return (None, 'p') if s == '/' else (s, mode)
+
+ if s in modes:
+ return (None, s) if s != mode else (None, mode)
+
+ if is_all_ge_n(s, '-', 4):
+ return (s, 'hr')
+
+ if mode == 'hr':
+ if is_all_ge_n(s, '-', 4):
+ return (s, 'hr')
+ return (s, 'p')
-next_mode = lambda s: 'p' if s == '/' else s
+ return (s, mode)
lst_strip = lambda lst: list( map( lambda s: s.strip(), lst ) )
@@ -125,6 +137,8 @@
res.append( { 'pre': s } )
elif mode == 'ul':
do_mode_ul(buf, res)
+ elif mode == 'hr':
+ res.extend( list( map( lambda s: { 'p': { 'hr': '/' } }, buf ) ) )
def ezmd(lst):
lst = ['p'] + lst
@@ -132,11 +146,11 @@
mode = ''
while lst:
s = lst.pop(0)
- if is_mode_switch(s, mode):
+ (s, nmd) = next_mode_switch(s, mode);
+ if nmd != mode:
do_mode(mode, buf, res)
- mode = next_mode(s)
- buf = []
- elif s != mode:
+ (mode, buf) = (nmd, [])
+ if s != None:
buf.append(s)
do_mode(mode, buf, res)
return res
$ cat v5.patch | patch -p1
foo_5.txt
h1
Python2とPython3での日本語文字列対応について
p
毎回、同じようにつまづいて、同じような感じで対応してます。
なので、いいかげん自分に判りやすいようにまとめておきます。
日本語対応といっても、ソースコード中に日本語を書くつもりはありません。
データはYAML形式のファイルで用意。
そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。
----
h2
結論
h3
日本語を含む文字列処理で .foramt() や .join() を使いたい
p
Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。
Python3 では日本語の有無に関係なく、素直にstrのままでよし。
h3
日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい
p
Python2 では素直に sys.stdin/sys.stdout を read/write。
Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。
Python2 の世界には .buffer は存在しないので注意。
----
pre
$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
/
ここはデフォルトp
p
ここは明示的にp
[[v2.patch]]
バージョン2のための[[ v2.patch | パッチ ]] となります。
[[http://kondoh.html.xdomain.jp/ezhtml/index.html | 簡易なHTMLパーサ 2018秋]]
これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。
pre
ここはpre
p
ここもpre
h1
ここもpre
/
ul
[[v2.patch]]
[[v3.patch]]
バージョン2のための[[ v2.patch | パッチ ]] となります。
これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。
p
ここはp
---
----
----
ここは暗黙のp
h3
ここはh3
---
----
----
---
p
ここはp
ul
標準入力からYAML形式のテキストを読み込み
yaml.load()でテキストをデータに
データの文字列2つを
ごにょごにょいじって
foo + ' ' + bar
.format()
.join()
yaml.dump()でデータを \
YAML形式のテキストにして
標準出力に書き出し
pre
ここはpre
実行してみます。
$ ./ezmd.py < foo_5.txt : - 毎回「うぅっ」とうなってます。 - p: hr: / - h2: 結論 : - p: - Python2 の世界には .buffer は存在しないので注意。 - p: hr: / - pre: | $ cat p2.py #!/usr/bin/env python2 : - p: - ここはp - p: - '---' - p: hr: / - p: hr: / - p: - ここは暗黙のp - h3: ここはh3--- - p: hr: / - p: hr: / - p: - '---' - p: - ここはp - ul: - li /: 標準入力からYAML形式のテキストを読み込み :
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_5.txt > foo_5.html
foo_5.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1>Python2とPython3での日本語文字列対応について</h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。</p>
<p><hr></p>
<h2>結論</h2>
<h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので注意。</p>
<p><hr></p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<p><a href="v2.patch">v2.patch</a></p>
<p>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。</p>
<p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p>
<p>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。
<li>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</ul>
<p>ここはp</p>
<p>---</p>
<p><hr></p>
<p><hr></p>
<p>ここは暗黙のp</p>
<h3>ここはh3---</h3>
<p><hr></p>
<p><hr></p>
<p>---</p>
<p>ここはp</p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li>データの文字列2つを
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し</ul>
<pre> ここはpre
</pre>
</body></html>
todo
追加してみます。
img, video ともに自分で使うときのパターンはほぼお決まりで、 a (href)タグと似たようなものです。
なので仕様もa (href)タグと同じような感じにします。
a (href)タグ同様に、pモードとulモードの文字列処理の箇所だけに、対応を入れます。
文字列中に [[ img | xxx ]] の記載があれば YAML形式の - img srcf="xxx": / を経て HTML形式で <img src="xxx"> に 文字列中に [[ video | xxx ]] の記載があれば YAML形式の - video src="xxx" controls playsinline: "" を経て HTML形式で <video src="xxx" controls playsinline></video> に
形式をa (href)タグの場合と合わせたので、 a (href)タグの箇所をちょっと改造するだけの対応になります。
v6.patch
diff -ur v5/ezmd.py v6/ezmd.py
--- v5/ezmd.py 2019-09-26 21:40:15.000000000 +0900
+++ v6/ezmd.py 2019-09-27 08:13:12.000000000 +0900
@@ -57,6 +57,13 @@
s_idx = lambda s, p, dv=-1: s.index(p) if p in s else dv
+def do_v1v2(v1, v2):
+ if v1 == 'img':
+ return { 'img src="{}"'.format(v2): '/' }
+ if v1 == 'video':
+ return { 'video src="{}" controls playsinline'.format(v2): '' }
+ return { 'a href="{}"'.format(v1): v2 } if v1 else v2
+
def do_str(s):
# a href
(h, t) = ('[[', ']]')
@@ -65,8 +72,8 @@
s3 = lst_strip( ( s[:ih], s[ih+len(h):it], s[it+len(t):] ) )
m = s3[1]
if m:
- (href, v) = lst_strip( m.split('|') ) if '|' in m else (m, m)
- s3[1] = { 'a href="{}"'.format(href): v } if href else v
+ (v1, v2) = lst_strip( m.split('|') ) if '|' in m else (m, m)
+ s3[1] = do_v1v2(v1, v2)
lst = list( filter( lambda o: o, s3 ) )
return lst[0] if len(lst) == 1 else lst
return s
$ cat v6.patch | patch -p1
foo_6.txt
h1
Python2とPython3での日本語文字列対応について
p
毎回、同じようにつまづいて、同じような感じで対応してます。
なので、いいかげん自分に判りやすいようにまとめておきます。
日本語対応といっても、ソースコード中に日本語を書くつもりはありません。
データはYAML形式のファイルで用意。
そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。
----
h2
結論
h3
日本語を含む文字列処理で .foramt() や .join() を使いたい
p
Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。
Python3 では日本語の有無に関係なく、素直にstrのままでよし。
h3
日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい
p
Python2 では素直に sys.stdin/sys.stdout を read/write。
Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。
Python2 の世界には .buffer は存在しないので [[img|beat.jpg]] 注意。
----
pre
$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
/
ここはデフォルトp
p
ここは明示的にp
[[v2.patch]]
バージョン2のための[[ v2.patch | パッチ ]] となります。
[[http://kondoh.html.xdomain.jp/ezhtml/index.html | 簡易なHTMLパーサ 2018秋]]
これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。
pre
ここはpre
p
ここもpre
h1
ここもpre
/
ul
[[v2.patch]]
[[v3.patch]]
バージョン2のための[[ v2.patch | パッチ ]] となります。
これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。
[[ img | beat.jpg ]]
[[ video | cut.mp4 ]]
p
ここはp
---
----
----
ここは暗黙のp
h3
ここはh3
---
----
----
---
p
ここはp
[[video|http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4]]
ul
標準入力からYAML形式のテキストを読み込み
yaml.load()でテキストをデータに
データの文字列2つを
ごにょごにょいじって
foo + ' ' + bar
.format()
.join()
yaml.dump()でデータを \
YAML形式のテキストにして
標準出力に書き出し
pre
ここはpre
実行してみます。
$ ./ezmd.py < foo_6.txt : - p: - Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 - p: - Python3 では日本語の有無に関係なく、素直にstrのままでよし。 - h3: 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - p: - Python2 では素直に sys.stdin/sys.stdout を read/write。 - p: - Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 - p: - Python2 の世界には .buffer は存在しないので - img src="beat.jpg": / - 注意。 : - ul: - li /: a href="v2.patch": v2.patch - li /: a href="v3.patch": v3.patch - li /: - バージョン2のための - a href="v2.patch": パッチ - となります。 - li /: - これは - a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import": pythonのモジュールのインポート - について。 - li /: img src="beat.jpg": / - li /: video src="cut.mp4" controls playsinline: '' - p: - ここはp : - p: - ここはp - p: - video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline: '' - ul: - li /: 標準入力からYAML形式のテキストを読み込み
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_6.txt > foo_6.html
foo_6.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1>Python2とPython3での日本語文字列対応について</h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回「うぅっ」とうなってます。</p>
<p><hr></p>
<h2>結論</h2>
<h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので
<img src="beat.jpg">
注意。</p>
<p><hr></p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<p><a href="v2.patch">v2.patch</a></p>
<p>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。</p>
<p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p>
<p>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。
<li>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。
<li><img src="beat.jpg">
<li><video src="cut.mp4" controls playsinline></video></ul>
<p>ここはp</p>
<p>---</p>
<p><hr></p>
<p><hr></p>
<p>ここは暗黙のp</p>
<h3>ここはh3---</h3>
<p><hr></p>
<p><hr></p>
<p>---</p>
<p>ここはp</p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li>データの文字列2つを
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し</ul>
<pre> ここはpre
</pre>
</body></html>
todo
追加してみます。
sタグは「打ち消し線」の指定です。
これまた a (href)タグ同様に、pモードとulモードの文字列処理の箇所だけの対応で。
形式も強引にa (href)タグに合わせてしまいます。(^_^;
文字列中に [[ - | xxx ]] の記載があれば YAML形式の - s: xxx を経て HTML形式で <s> xxx </s> に
形式を強引にもa (href)タグの場合と合わせたので、 変更箇所は驚くほど軽微です。
v7.patch
diff -ur v6/ezmd.py v7/ezmd.py
--- v6/ezmd.py 2019-09-27 08:13:12.000000000 +0900
+++ v7/ezmd.py 2019-09-27 08:13:21.000000000 +0900
@@ -62,6 +62,8 @@
return { 'img src="{}"'.format(v2): '/' }
if v1 == 'video':
return { 'video src="{}" controls playsinline'.format(v2): '' }
+ if v1 == '-':
+ return { 's': v2 }
return { 'a href="{}"'.format(v1): v2 } if v1 else v2
def do_str(s):
$ cat v7.patch | patch -p1
foo_7.txt
h1
Python2とPython3での日本語文字列対応について
p
毎回、同じようにつまづいて、同じような感じで対応してます。
なので、いいかげん自分に判りやすいようにまとめておきます。
日本語対応といっても、ソースコード中に日本語を書くつもりはありません。
データはYAML形式のファイルで用意。
そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回[[ - |「うぅっ」]] 「ぬはぁ」とうなってます。
----
h2
結論
h3
日本語を含む文字列処理で .foramt() や .join() を使いたい
p
Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。
Python3 では日本語の有無に関係なく、素直にstrのままでよし。
h3
日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい
p
Python2 では素直に sys.stdin/sys.stdout を read/write。
Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。
Python2 の世界には .buffer は存在しないので [[img|beat.jpg]] 注意。
----
pre
$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
/
ここはデフォルトp
p
ここは明示的にp
[[v2.patch]]
バージョン2のための[[ v2.patch | パッチ ]] となります。
[[http://kondoh.html.xdomain.jp/ezhtml/index.html | 簡易なHTMLパーサ 2018秋]]
これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。
pre
ここはpre
p
ここもpre
h1
ここもpre
/
ul
[[v2.patch]]
[[v3.patch]]
バージョン2のための[[ v2.patch | パッチ ]] となります。
これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。
[[ img | beat.jpg ]]
[[ video | cut.mp4 ]]
p
ここはp
---
----
----
ここは暗黙のp
h3
ここはh3
---
----
----
---
p
ここはp
[[video|http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4]]
ul
標準入力からYAML形式のテキストを読み込み
yaml.load()でテキストをデータに
[[-|データの文字列2つを]]
ごにょごにょいじって
foo + ' ' + bar
.format()
.join()
yaml.dump()でデータを \
YAML形式のテキストにして
標準出力に書き出し
pre
ここはpre
実行してみます。
$ ./ezmd.py < foo_7.txt : - p: - そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 - 毎回 - s: 「うぅっ」 - 「ぬはぁ」とうなってます。 - p: hr: / : - ul: - li /: 標準入力からYAML形式のテキストを読み込み - li /: yaml.load()でテキストをデータに - li /: s: データの文字列2つを - li /: ごにょごにょいじって :
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_7.txt > foo_7.html
foo_7.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1>Python2とPython3での日本語文字列対応について</h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回
<s>「うぅっ」</s>
「ぬはぁ」とうなってます。</p>
<p><hr></p>
<h2>結論</h2>
<h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので
<img src="beat.jpg">
注意。</p>
<p><hr></p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<p><a href="v2.patch">v2.patch</a></p>
<p>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。</p>
<p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p>
<p>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。
<li>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。
<li><img src="beat.jpg">
<li><video src="cut.mp4" controls playsinline></video></ul>
<p>ここはp</p>
<p>---</p>
<p><hr></p>
<p><hr></p>
<p>ここは暗黙のp</p>
<h3>ここはh3---</h3>
<p><hr></p>
<p><hr></p>
<p>---</p>
<p>ここはp</p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li><s>データの文字列2つを</s>
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し</ul>
<pre> ここはpre
</pre>
</body></html>
todo
目次を自動生成する機能を追加してみます。
さすがにこの機能は2 passになります。
'index'だけの行が現れると目次モード。
そこから他のモードになるまでの区間に目次を挿入します。
目次モード中の箇所に、目次作成のためのパラメータを指定します。
index パラメータ
パラメータは、目次にするヘッダタグの種別の範囲を指定します。
範囲指定はPythonのリストのスライスの指定のようにします。
index 2:5
lst[2:5] なので目次にする対象は h2, h3, h4
index 3:
lst[3:] なので、目次にする対象は h3, h4, ....
index :3
lst[:3] なので、目次にする対象は h1, h2
index
パラメータの指定がなければ lst[:] 扱いで、全てのヘッダタグを対象にします。
目次の形式は、ヘッダタグの階層に従って ulタグの入れ子の構成にします。
ulタグの処理は既に実装してるので、 ヘッダの番号に応じて字下げしたテキストデータを作り、 ulタグとして処理すれば楽チンですね。
v8.patch
diff -ur v7/ezmd.py v8/ezmd.py
--- v7/ezmd.py 2019-09-27 08:13:21.000000000 +0900
+++ v8/ezmd.py 2019-09-27 09:23:15.000000000 +0900
@@ -5,7 +5,7 @@
import nkf
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
-modes = heads + [ 'p', 'pre', 'ul' ]
+modes = heads + [ 'p', 'pre', 'ul', 'index' ]
is_all_ge_n = lambda s, c, n: all( map( lambda c_: c_ == c, s ) ) and len(s) >= n
@@ -61,7 +61,7 @@
if v1 == 'img':
return { 'img src="{}"'.format(v2): '/' }
if v1 == 'video':
- return { 'video src="{}" controls playsinline'.format(v2): '' }
+ return { 'video src="{}" controls playsinline'.format(v2): '' }
if v1 == '-':
return { 's': v2 }
return { 'a href="{}"'.format(v1): v2 } if v1 else v2
@@ -115,12 +115,16 @@
res.extend( list( map(lst_to, lsts) ) )
-def do_mode(mode, buf, res):
+def do_mode(mode, buf, res, hd_names):
if mode in heads:
buf = lst_strip(buf)
buf = list( filter( lambda s: s!='', buf ) )
s = ''.join(buf)
- res.append( { mode: s } )
+ (h_i, n) = ( int(mode[1:]), len(hd_names) )
+ name = 'c_{}_{}'.format(h_i, n)
+ res.append( { mode: { 'a name="{}"'.format(name): s } } )
+ hd_names.append( (h_i, n, name, s) )
+
elif mode == 'p':
buf = lst_strip(buf)
@@ -148,20 +152,62 @@
do_mode_ul(buf, res)
elif mode == 'hr':
res.extend( list( map( lambda s: { 'p': { 'hr': '/' } }, buf ) ) )
+ elif mode == 'index':
+ buf = lst_strip(buf)
+ buf = list( filter( lambda s: s!='', buf ) )
+ res.append( { 'index': buf } ) # continue to 2 pass
+
+def do_index(lst, hd_names):
+
+ def slice_get(buf):
+ slc = ':'
+ for s in buf:
+ if ':' in s:
+ slc = s
+ elif s.isdigit():
+ slc = s + ':{}'.format( int(s)+1 )
+ if slc:
+ break
+ return slc
+
+ def names_get(hd_names, slc):
+ sel = range(10)
+ try:
+ sel = eval( str(sel) + '[{}]'.format(slc) )
+ except:
+ pass
+ return list( filter( lambda vs: vs[0] in sel, hd_names ) )
+
+ res = []
+ for d in lst:
+ if 'index' in d:
+ slc =slice_get( d.get('index') )
+ names = names_get(hd_names, slc)
+
+ func = lambda h_i, n, name, s: ' ' * h_i + '[[#{}|'.format(name) + s + ']]'
+ buf = list( map( lambda vs: func(*vs), names ) )
+ ul_res = []
+ do_mode_ul(buf, ul_res)
+
+ res.extend(ul_res)
+ else:
+ res.append(d)
+ return res
def ezmd(lst):
lst = ['p'] + lst
- (buf, res) = ( [], [] )
+ (buf, res, hd_names) = ( [], [], [] )
mode = ''
while lst:
s = lst.pop(0)
(s, nmd) = next_mode_switch(s, mode);
if nmd != mode:
- do_mode(mode, buf, res)
+ do_mode(mode, buf, res, hd_names)
(mode, buf) = (nmd, [])
if s != None:
buf.append(s)
- do_mode(mode, buf, res)
+ do_mode(mode, buf, res, hd_names)
+ res = do_index(res, hd_names)
return res
def yaml_dump(o):
$ cat v8.patch | patch -p1
foo_8.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1><a name="c_1_0">Python2とPython3での日本語文字列対応について</a></h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回
<s>「うぅっ」</s>
「ぬはぁ」とうなってます。</p>
<p><hr></p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2: の場合</p>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul>
<p><hr></p>
<p>:4 の場合</p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2:3 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>2 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>3 の場合</p>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul>
<p><hr></p>
<h2><a name="c_2_1">結論</a></h2>
<h3><a name="c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a></h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3><a name="c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a></h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので
<img src="beat.jpg">
注意。</p>
<p><hr></p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<p><a href="v2.patch">v2.patch</a></p>
<p>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。</p>
<p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p>
<p>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。
<li>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。
<li><img src="beat.jpg">
<li><video src="cut.mp4" controls playsinline></video></ul>
<p>ここはp</p>
<p>---</p>
<p><hr></p>
<p><hr></p>
<p>ここは暗黙のp</p>
<h3><a name="c_3_4">ここはh3---</a></h3>
<p><hr></p>
<p><hr></p>
<p>---</p>
<p>ここはp</p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li><s>データの文字列2つを</s>
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し</ul>
<pre> ここはpre
</pre>
</body></html>
$ cat foo_8.txt : そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回[[ - |「うぅっ」]] 「ぬはぁ」とうなってます。 ---- index ---- p 2: の場合 index 2: ---- p :4 の場合 index :4 ---- p 2:3 の場合 index 2:3 ---- p 2 の場合 index 2 ---- p 3 の場合 index 3 ---- h2 結論
実行してみます。
$ ./ezmd.py < foo_8.txt : - p: - そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 - 毎回 - s: 「うぅっ」 - 「ぬはぁ」とうなってます。 - p: hr: / - ul: - li /: a href="#c_1_0": Python2とPython3での日本語文字列対応について - ul: - li /: a href="#c_2_1": 結論 - ul: - li /: a href="#c_3_2": 日本語を含む文字列処理で .foramt() や .join() を使いたい - li /: a href="#c_3_3": 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - li /: a href="#c_3_4": ここはh3--- - p: hr: / - p: - '2: の場合' - ul: - li /: a href="#c_2_1": 結論 - ul: - li /: a href="#c_3_2": 日本語を含む文字列処理で .foramt() や .join() を使いたい - li /: a href="#c_3_3": 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - li /: a href="#c_3_4": ここはh3--- - p: hr: / - p: - :4 の場合 - ul: - li /: a href="#c_1_0": Python2とPython3での日本語文字列対応について - ul: - li /: a href="#c_2_1": 結論 - ul: - li /: a href="#c_3_2": 日本語を含む文字列処理で .foramt() や .join() を使いたい - li /: a href="#c_3_3": 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - li /: a href="#c_3_4": ここはh3--- - p: hr: / - p: - 2:3 の場合 - ul: - li /: a href="#c_2_1": 結論 - p: hr: / - p: - 2 の場合 - ul: - li /: a href="#c_2_1": 結論 - p: hr: / - p: - 3 の場合 - ul: - li /: a href="#c_3_2": 日本語を含む文字列処理で .foramt() や .join() を使いたい - li /: a href="#c_3_3": 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - li /: a href="#c_3_4": ここはh3--- - p: hr: / - h2: a name="c_2_1": 結論
さすがにこれは、パッとみて大丈夫かどうか分かりかねますね。
$ ./to_html.py foo_head.yaml foo_8.txt | tee foo_8.html | nkf -u : <p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回 <s>「うぅっ」</s> 「ぬはぁ」とうなってます。</p> <p><hr></p> <ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a> <ul><li><a href="#c_2_1">結論</a> <ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a> <li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a> <li><a href="#c_3_4">ここはh3---</a></ul></ul></ul> <p><hr></p> <p>2: の場合</p> <ul><li><a href="#c_2_1">結論</a> <ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a> <li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a> <li><a href="#c_3_4">ここはh3---</a></ul></ul> <p><hr></p> <p>:4 の場合</p> <ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a> <ul><li><a href="#c_2_1">結論</a> <ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a> <li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a> <li><a href="#c_3_4">ここはh3---</a></ul></ul></ul> <p><hr></p> <p>2:3 の場合</p> <ul><li><a href="#c_2_1">結論</a></ul> <p><hr></p> <p>2 の場合</p> <ul><li><a href="#c_2_1">結論</a></ul> <p><hr></p> <p>3 の場合</p> <ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a> <li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a> <li><a href="#c_3_4">ここはh3---</a></ul> <p><hr></p> <h2><a name="c_2_1">結論</a></h2> :
むー、まぁ、百聞は一見にしかず
foo_8.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1><a name="c_1_0">Python2とPython3での日本語文字列対応について</a></h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回
<s>「うぅっ」</s>
「ぬはぁ」とうなってます。</p>
<p><hr></p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2: の場合</p>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul>
<p><hr></p>
<p>:4 の場合</p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2:3 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>2 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>3 の場合</p>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul>
<p><hr></p>
<h2><a name="c_2_1">結論</a></h2>
<h3><a name="c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a></h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3><a name="c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a></h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので
<img src="beat.jpg">
注意。</p>
<p><hr></p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<p><a href="v2.patch">v2.patch</a></p>
<p>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。</p>
<p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p>
<p>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。
<li>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。
<li><img src="beat.jpg">
<li><video src="cut.mp4" controls playsinline></video></ul>
<p>ここはp</p>
<p>---</p>
<p><hr></p>
<p><hr></p>
<p>ここは暗黙のp</p>
<h3><a name="c_3_4">ここはh3---</a></h3>
<p><hr></p>
<p><hr></p>
<p>---</p>
<p>ここはp</p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li><s>データの文字列2つを</s>
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し</ul>
<pre> ここはpre
</pre>
</body></html>
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1><a name="c_1_0">Python2とPython3での日本語文字列対応について</a></h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回
<s>「うぅっ」</s>
「ぬはぁ」とうなってます。</p>
<p><hr></p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2: の場合</p>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul>
<p><hr></p>
<p>:4 の場合</p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2:3 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>2 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>3 の場合</p>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul>
<p><hr></p>
<h2><a name="c_2_1">結論</a></h2>
<h3><a name="c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a></h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3><a name="c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a></h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので
<img src="beat.jpg">
注意。</p>
<p><hr></p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<p><a href="v2.patch">v2.patch</a></p>
<p>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。</p>
<p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p>
<p>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。
<li>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。
<li><img src="beat.jpg">
<li><video src="cut.mp4" controls playsinline></video></ul>
<p>ここはp</p>
<p>---</p>
<p><hr></p>
<p><hr></p>
<p>ここは暗黙のp</p>
<h3><a name="c_3_4">ここはh3---</a></h3>
<p><hr></p>
<p><hr></p>
<p>---</p>
<p>ここはp</p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li><s>データの文字列2つを</s>
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し</ul>
<pre> ここはpre
</pre>
</body></html>
大丈夫そうですね。
todo
自分ではいつもheadタグには日本語は書かないので、 ここは安易に
v9.patch
diff -ur v8/to_html.py v9/to_html.py
--- v8/to_html.py 2019-09-22 16:55:14.000000000 +0900
+++ v9/to_html.py 2019-09-27 22:15:57.000000000 +0900
@@ -4,11 +4,18 @@
import subprocess
if __name__ == "__main__":
- if len(sys.argv) < 3:
- print( 'Usage: {} head.yaml body.txt'.format( sys.argv[0] ) )
+ n = len(sys.argv)
+ if n < 3:
+ print( 'Usage: {} head.yaml body.txt [title]'.format( sys.argv[0] ) )
sys.exit(1)
-
- cmd = "( echo '<html><head>' ; ./ezhtml.py y < {} ; echo '</head><body>' ; ./ezmd.py < {} | ./ezhtml.py y ; echo '</body></html>' ) | nkf -j";
- cmd = cmd.format( sys.argv[1], sys.argv[2] )
+
+ title = sys.argv[3] if n > 3 else ''
+
+ cmd_title = "sed 's/^- title: .*/- title: {}/'".format(title) if title else 'cat'
+ cmd_hd = 'cat {} | {} | ./ezhtml.py y'.format( sys.argv[1], cmd_title )
+
+ cmd = "( echo '<html><head>' ; {} ; echo '</head><body>' ; ./ezmd.py < {} | ./ezhtml.py y ; echo '</body></html>' ) | nkf -j";
+ cmd = cmd.format( cmd_hd, sys.argv[2] )
+ #print(cmd)
subprocess.call(cmd, shell=True)
# EOF
$ cat v9.patch | patch -p1
実行してみます。
$ ./to_html.py Usage: ./to_html.py head.yaml body.txt [title] $ ./to_html.py foo_head.yaml foo_8.txt | grep title <title>py23str</title> $ ./to_html.py foo_head.yaml foo_8.txt 'sample page' | grep title <title>sample page</title> $ ./to_html.py foo_head.yaml foo_8.txt 'sample page' > foo_9.html
OK
foo_9.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>sample page</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1><a name="c_1_0">Python2とPython3での日本語文字列対応について</a></h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回
<s>「うぅっ」</s>
「ぬはぁ」とうなってます。</p>
<p><hr></p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2: の場合</p>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul>
<p><hr></p>
<p>:4 の場合</p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2:3 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>2 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>3 の場合</p>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul>
<p><hr></p>
<h2><a name="c_2_1">結論</a></h2>
<h3><a name="c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a></h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<h3><a name="c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a></h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので
<img src="beat.jpg">
注意。</p>
<p><hr></p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<p><a href="v2.patch">v2.patch</a></p>
<p>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。</p>
<p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p>
<p>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。
<li>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。
<li><img src="beat.jpg">
<li><video src="cut.mp4" controls playsinline></video></ul>
<p>ここはp</p>
<p>---</p>
<p><hr></p>
<p><hr></p>
<p>ここは暗黙のp</p>
<h3><a name="c_3_4">ここはh3---</a></h3>
<p><hr></p>
<p><hr></p>
<p>---</p>
<p>ここはp</p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li><s>データの文字列2つを</s>
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し</ul>
<pre> ここはpre
</pre>
</body></html>
todo
色々試してみて不具合でました。
ulタグの処理前に、字下げの絡みで行の結合をする箇所。
def esc_join(lst): res = [] for s in lst: if res and res[-1] and res[-1][-1] == '\\': t = res[-1][:-1] res[-1] = strip_tail(t) + strip_head(s) else: res.append(s) return res
res[-1]が空文字列''の場合に、''[-1]になってアクセスでエラーが出る事がありました。
- if res and res[-1][-1] == '\\': + if res and res[-1] and res[-1][-1] == '\\':
な修正をしておきます。
次の調整を入れておきます。
v10.patch
diff -ur v9/ezmd.py v10/ezmd.py
--- v9/ezmd.py 2019-09-27 09:23:15.000000000 +0900
+++ v10/ezmd.py 2019-09-27 22:16:31.000000000 +0900
@@ -45,10 +45,17 @@
s = s[1:]
return (i, s)
+def cut_verb_idt(lst):
+ lst_ = list( filter( lambda s: s != '', lst ) )
+ i = min( map( lambda s: idt_cnt(s)[0], lst_ ) )
+ if i > 0:
+ lst = list( map( lambda s: s[i:], lst ) )
+ return lst
+
def esc_join(lst):
res = []
for s in lst:
- if res and res[-1][-1] == '\\':
+ if res and res[-1] and res[-1][-1] == '\\':
t = res[-1][:-1]
res[-1] = strip_tail(t) + strip_head(s)
else:
@@ -146,6 +153,7 @@
while buf and buf[-1] == '':
buf.pop()
if buf:
+ buf = cut_verb_idt(buf)
s = '\n'.join(buf) + '\n'
res.append( { 'pre': s } )
elif mode == 'ul':
@@ -225,6 +233,7 @@
b = nkf.get_stdin()
(s, nkf_opt) = nkf.to_str(b)
lst = s.split('\n')
+ lst = list( map( strip_tail, lst ) )
lst = ezmd(lst)
$ cat v10.patch | patch -p1
では満を持して、このページ自身もこの仕様のテキストで書いてみましょう。
このテキストファイルから
$ ./to_html.py head.yaml index.ez.txt ezmd > index.html
となります。
(再帰だ〜)
todo
コードを見直してみて、ちょっとした修正や調整をしました。
修正確認用に index.ez.txt の時の結果のHTMLを index.ez.html として置いておきます。
$ cp index.html index.ez.html
v11.patch
diff -ur v10/ezmd.py v11/ezmd.py
--- v10/ezmd.py 2019-09-27 22:16:31.000000000 +0900
+++ v11/ezmd.py 2019-09-30 00:19:27.000000000 +0900
@@ -26,31 +26,30 @@
return (s, mode)
+to_lst = lambda o: o if type(o) == list else [o]
+from_lst = lambda lst: lst[0] if len(lst) == 1 else lst
+flat_map = lambda f, lst: sum( map( lambda o: to_lst( f(o) ), lst ), [] )
+
lst_strip = lambda lst: list( map( lambda s: s.strip(), lst ) )
-def strip_head(s):
- while s and s[0] in (' ', '\t'):
- s = s[1:]
- return s
+strip_head = lambda s: strip_head(s[1:]) if s and s[0] in (' ', '\t') else s
+strip_tail = lambda s: strip_tail(s[:-1]) if s and s[-1] in (' ', '\t') else s
-def strip_tail(s):
- while s and s[-1] in (' ', '\t'):
- s = s[:-1]
- return s
+idt_get = lambda s: 1 + idt_get(s[1:]) if s and s[0] in (' ', '\t') else 0
def idt_cnt(s):
- i = 0
- while s and s[0] in (' ', '\t'):
- i += 1
- s = s[1:]
- return (i, s)
+ i = idt_get(s)
+ return ( i, s[i:] )
+
+cut_empty = lambda lst: list( filter( lambda s: s != '', lst ) )
def cut_verb_idt(lst):
- lst_ = list( filter( lambda s: s != '', lst ) )
- i = min( map( lambda s: idt_cnt(s)[0], lst_ ) )
- if i > 0:
- lst = list( map( lambda s: s[i:], lst ) )
- return lst
+ i = min( map( idt_get, cut_empty(lst) ) )
+ return list( map( lambda s: s[i:], lst ) ) if i > 0 else lst
+
+cut_h_empty = lambda lst: cut_h_empty(lst[1:]) if lst and lst[0] == '' else lst
+cut_t_empty = lambda lst: cut_t_empty(lst[:-1]) if lst and lst[-1] == '' else lst
+cut_ht_empty = lambda lst: cut_t_empty( cut_h_empty(lst) )
def esc_join(lst):
res = []
@@ -83,8 +82,7 @@
if m:
(v1, v2) = lst_strip( m.split('|') ) if '|' in m else (m, m)
s3[1] = do_v1v2(v1, v2)
- lst = list( filter( lambda o: o, s3 ) )
- return lst[0] if len(lst) == 1 else lst
+ return from_lst( cut_empty(s3) )
return s
def do_mode_ul(buf, res):
@@ -125,7 +123,7 @@
def do_mode(mode, buf, res, hd_names):
if mode in heads:
buf = lst_strip(buf)
- buf = list( filter( lambda s: s!='', buf ) )
+ buf = cut_empty(buf)
s = ''.join(buf)
(h_i, n) = ( int(mode[1:]), len(hd_names) )
name = 'c_{}_{}'.format(h_i, n)
@@ -144,14 +142,10 @@
lsts.append(lst)
lst = []
for lst in lsts:
- to_lst = lambda o: o if type(o) == list else [o]
- lst = sum( map( lambda s: to_lst( do_str(s) ), lst ), [] )
+ lst = flat_map(do_str, lst)
res.append( { 'p': lst } )
elif mode == 'pre':
- while buf and buf[0] == '':
- buf.pop(0)
- while buf and buf[-1] == '':
- buf.pop()
+ buf = cut_ht_empty(buf)
if buf:
buf = cut_verb_idt(buf)
s = '\n'.join(buf) + '\n'
@@ -159,10 +153,10 @@
elif mode == 'ul':
do_mode_ul(buf, res)
elif mode == 'hr':
- res.extend( list( map( lambda s: { 'p': { 'hr': '/' } }, buf ) ) )
+ res.extend( [ { 'p': { 'hr': '/' } } ] * len(buf) )
elif mode == 'index':
buf = lst_strip(buf)
- buf = list( filter( lambda s: s!='', buf ) )
+ buf = cut_empty(buf)
res.append( { 'index': buf } ) # continue to 2 pass
def do_index(lst, hd_names):
@@ -186,21 +180,17 @@
pass
return list( filter( lambda vs: vs[0] in sel, hd_names ) )
- res = []
- for d in lst:
- if 'index' in d:
- slc =slice_get( d.get('index') )
- names = names_get(hd_names, slc)
-
- func = lambda h_i, n, name, s: ' ' * h_i + '[[#{}|'.format(name) + s + ']]'
- buf = list( map( lambda vs: func(*vs), names ) )
- ul_res = []
- do_mode_ul(buf, ul_res)
+ def f(buf):
+ names = names_get(hd_names, slice_get(buf) )
- res.extend(ul_res)
- else:
- res.append(d)
- return res
+ func = lambda h_i, n, name, s: ' ' * h_i + '[[#{}|'.format(name) + s + ']]'
+ buf = list( map( lambda vs: func(*vs), names ) )
+
+ ul_res = []
+ do_mode_ul(buf, ul_res)
+ return ul_res
+
+ return flat_map( lambda d: f( d.get('index') ) if 'index' in d else d, lst )
def ezmd(lst):
lst = ['p'] + lst
$ cat v11.patch | patch -p1 $ ./to_html.py head.yaml index.ez.txt ezmd | diff -u index.ez.html - $
動作的に変化なしでOK。
todo
改行のbrタグはあまり使わないのですが、 たまーに使う場面がでてくるので対応してみます。
使うとしたらpモード中や、ulモード中。
となると、a (href) のときのコードの箇所
def do_str(s): # a href (h, t) = ('[[', ']]') (ih, it) = list( map( lambda p: s_idx(s, p), (h, t) ) ) if 0 <= ih and ih < it: s3 = lst_strip( ( s[:ih], s[ih+len(h):it], s[it+len(t):] ) ) m = s3[1] if m: (v1, v2) = lst_strip( m.split('|') ) if '|' in m else (m, m) s3[1] = do_v1v2(v1, v2) return from_lst( cut_empty(s3) ) return s
ここに追加すれば良さそう...
と、、、この a (href) のコード、、、
よく見ると1つの行に2個以上のアンカーに対応できてないのでは?
$ echo hello | ./ezmd.py - p: - hello $ echo hello [[foo]] | ./ezmd.py - p: - hello - a href="foo": foo $ echo hello [[foo]] hoge [[bar]] | ./ezmd.py - p: - hello - a href="foo": foo - hoge [[bar]]
やっぱり!
brタグの対応を入れつつ、この不具合も直しておきます。
brタグ仕様は、文字列中の '\\' + 'n' を見つけると、 { 'br': '/' } を経ての <br> という事で。
v12.patch
diff -ur v11/ezmd.py v12/ezmd.py
--- v11/ezmd.py 2019-09-30 00:19:27.000000000 +0900
+++ v12/ezmd.py 2019-09-30 01:52:00.000000000 +0900
@@ -72,19 +72,41 @@
return { 's': v2 }
return { 'a href="{}"'.format(v1): v2 } if v1 else v2
-def do_str(s):
- # a href
+def do_br(s):
+ p = '\\n'
+ if p in s:
+ lst = flat_map( lambda s_: [ s_, { 'br': '/' } ], s.split(p) )[:-1]
+ return from_lst( cut_empty(lst) )
+ return s
+
+def do_a_href(s):
(h, t) = ('[[', ']]')
(ih, it) = list( map( lambda p: s_idx(s, p), (h, t) ) )
if 0 <= ih and ih < it:
s3 = lst_strip( ( s[:ih], s[ih+len(h):it], s[it+len(t):] ) )
- m = s3[1]
- if m:
- (v1, v2) = lst_strip( m.split('|') ) if '|' in m else (m, m)
- s3[1] = do_v1v2(v1, v2)
- return from_lst( cut_empty(s3) )
+
+ def mcv(s):
+ (v1, v2) = lst_strip( s.split('|') ) if '|' in s else (s, s)
+ return do_v1v2(v1, v2)
+
+ cvs = ( (lambda s: s), mcv, do_a_href )
+ f = lambda i: cvs[i]( s3[i] )
+ return from_lst( cut_empty( flat_map( f, range(3) ) ) )
return s
+#
+# sol : str or lst
+#
+def map_sol(f_s_ret_sol, sol):
+ f = lambda o: o if type(o) == dict else f_s_ret_sol(o)
+ return flat_map(f, sol) if type(sol) == list else f_s_ret_sol(sol)
+
+def do_str(sol): # str or list
+ cvs = (do_br, do_a_href)
+ for cv in cvs:
+ sol = map_sol(cv, sol)
+ return sol
+
def do_mode_ul(buf, res):
buf = esc_join(buf)
buf = list( filter( lambda s: s.strip(), buf ) )
$ cat v12.patch | patch -p1
まず、複数のアンカー対応の確認から
$ echo hello | ./ezmd.py - p: - hello $ echo hello [[foo]] | ./ezmd.py - p: - hello - a href="foo": foo $ echo hello [[foo]] hoge [[bar]] | ./ezmd.py - p: - hello - a href="foo": foo - hoge - a href="bar": bar
OK。
つづいてbrの改行の確認を。
確認用のデータ
$ cat v12.patch | patch -p1 $ diff -u foo_8.txt foo_12.txt --- foo_8.txt 2019-09-27 13:23:29.000000000 +0900 +++ foo_12.txt 2019-09-30 01:42:26.000000000 +0900 @@ -53,6 +53,12 @@ Python3 では日本語の有無に関係なく、素直にstrのままでよし。 + (改行を入れてみると) + Python2 では日本語を含む文字列は\n .encode('utf-8')して UTF-8 で保持。 + + Python3\n では日本語の有無に関係なく、\n素直にstrのままでよし。\n + ここは改行の直後 + h3 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい @@ -94,6 +100,8 @@ バージョン2のための[[ v2.patch | パッチ ]] となります。 + [[v2.patch]] と [[v3.patch]] と [[v4.patch]] + [[http://kondoh.html.xdomain.jp/ezhtml/index.html | 簡易なHTMLパーサ 2018秋]] これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。 @@ -109,6 +117,10 @@ ul [[v2.patch]] [[v3.patch]] +[[v2.patch]] [[v3.patch]] + [[v2.patch]] + [[v3.patch]] + [[v2.patch]] [[v3.patch]] バージョン2のための[[ v2.patch | パッチ ]] となります。 これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。 [[ img | beat.jpg ]] @@ -148,6 +160,9 @@ yaml.dump()でデータを \ YAML形式のテキストにして 標準出力に書き出し + 長い文字列「こんちには 世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには bar=世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには」の場合 + 改行を入れてみると + 長い文字列\n「こんちには 世界(^_^)\nこんちには(^_^)\n世界(^_^)\nfoo=こんちには \nbar=世界(^_^)\nこんちには(^_^)\n世界(^_^)\nfoo=こんちには」\nの場合 pre ここはpre
実行してみます。
$ ./ezmd.py < foo_12.txt : - p: - Python3 では日本語の有無に関係なく、素直にstrのままでよし。 - p: - (改行を入れてみると) - Python2 では日本語を含む文字列は - br: / - ' .encode(''utf-8'')して UTF-8 で保持。' - p: - Python3 - br: / - ' では日本語の有無に関係なく、' - br: / - 素直にstrのままでよし。 - br: / - ここは改行の直後 - h3: a name="c_3_3": 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい : - p: - バージョン2のための - a href="v2.patch": パッチ - となります。 - p: - a href="v2.patch": v2.patch - と - a href="v3.patch": v3.patch - と - a href="v4.patch": v4.patch - p: - a href="http://kondoh.html.xdomain.jp/ezhtml/index.html": 簡易なHTMLパーサ 2018秋 - p: - これは - a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import": pythonのモジュールのインポート - について。 : - ul: - li /: a href="v2.patch": v2.patch - li /: a href="v3.patch": v3.patch - li /: - a href="v2.patch": v2.patch - a href="v3.patch": v3.patch - ul: - li /: a href="v2.patch": v2.patch - li /: a href="v3.patch": v3.patch - li /: - a href="v2.patch": v2.patch - a href="v3.patch": v3.patch - li /: - バージョン2のための - a href="v2.patch": パッチ - となります。 - li /: - これは - a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import": pythonのモジュールのインポート - について。 - li /: img src="beat.jpg": / : - li /: yaml.dump()でデータをYAML形式のテキストにして - li /: 標準出力に書き出し - li /: 長い文字列「こんちには 世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには bar=世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには」の場合 - li /: 改行を入れてみると - li /: - 長い文字列 - br: / - 「こんちには 世界(^_^) - br: / - こんちには(^_^) - br: / - 世界(^_^) - br: / - 'foo=こんちには ' - br: / - bar=世界(^_^) - br: / - こんちには(^_^) - br: / - 世界(^_^) - br: / - foo=こんちには」 - br: / - の場合 - pre: | ここはpre
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_12.txt > foo_12.html $ nkf -u foo_12.html : <p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p> <p>(改行を入れてみると) Python2 では日本語を含む文字列は <br> .encode('utf-8')して UTF-8 で保持。</p> <p>Python3 <br> では日本語の有無に関係なく、 <br> 素直にstrのままでよし。 <br> ここは改行の直後</p> <h3><a name="c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a></h3> : <p>バージョン2のための <a href="v2.patch">パッチ</a> となります。</p> <p><a href="v2.patch">v2.patch</a> と <a href="v3.patch">v3.patch</a> と <a href="v4.patch">v4.patch</a></p> <p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p> <p>これは <a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a> について。</p> : <ul><li><a href="v2.patch">v2.patch</a> <li><a href="v3.patch">v3.patch</a> <li><a href="v2.patch">v2.patch</a> <a href="v3.patch">v3.patch</a> <ul><li><a href="v2.patch">v2.patch</a> <li><a href="v3.patch">v3.patch</a> <li><a href="v2.patch">v2.patch</a> <a href="v3.patch">v3.patch</a></ul> <li>バージョン2のための <a href="v2.patch">パッチ</a> となります。 <li>これは <a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a> について。 <li><img src="beat.jpg"> : <li>yaml.dump()でデータをYAML形式のテキストにして <li>標準出力に書き出し <li>長い文字列「こんちには 世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには bar=世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには」の場合 <li>改行を入れてみると <li>長い文字列 <br> 「こんちには 世界(^_^) <br> こんちには(^_^) <br> 世界(^_^) <br> foo=こんちには <br> bar=世界(^_^) <br> こんちには(^_^) <br> 世界(^_^) <br> foo=こんちには」 <br> の場合</ul> <pre>ここはpre :
foo_12.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1><a name="c_1_0">Python2とPython3での日本語文字列対応について</a></h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回
<s>「うぅっ」</s>
「ぬはぁ」とうなってます。</p>
<p><hr></p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2: の場合</p>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul>
<p><hr></p>
<p>:4 の場合</p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2:3 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>2 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>3 の場合</p>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul>
<p><hr></p>
<h2><a name="c_2_1">結論</a></h2>
<h3><a name="c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a></h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<p>(改行を入れてみると)
Python2 では日本語を含む文字列は
<br>
.encode('utf-8')して UTF-8 で保持。</p>
<p>Python3
<br>
では日本語の有無に関係なく、
<br>
素直にstrのままでよし。
<br>
ここは改行の直後</p>
<h3><a name="c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a></h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので
<img src="beat.jpg">
注意。</p>
<p><hr></p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<p><a href="v2.patch">v2.patch</a></p>
<p>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。</p>
<p><a href="v2.patch">v2.patch</a>
と
<a href="v3.patch">v3.patch</a>
と
<a href="v4.patch">v4.patch</a></p>
<p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p>
<p>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li><a href="v2.patch">v2.patch</a>
<a href="v3.patch">v3.patch</a>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li><a href="v2.patch">v2.patch</a>
<a href="v3.patch">v3.patch</a></ul>
<li>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。
<li>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。
<li><img src="beat.jpg">
<li><video src="cut.mp4" controls playsinline></video></ul>
<p>ここはp</p>
<p>---</p>
<p><hr></p>
<p><hr></p>
<p>ここは暗黙のp</p>
<h3><a name="c_3_4">ここはh3---</a></h3>
<p><hr></p>
<p><hr></p>
<p>---</p>
<p>ここはp</p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li><s>データの文字列2つを</s>
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し
<li>長い文字列「こんちには 世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには bar=世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには」の場合
<li>改行を入れてみると
<li>長い文字列
<br>
「こんちには 世界(^_^)
<br>
こんちには(^_^)
<br>
世界(^_^)
<br>
foo=こんちには
<br>
bar=世界(^_^)
<br>
こんちには(^_^)
<br>
世界(^_^)
<br>
foo=こんちには」
<br>
の場合</ul>
<pre>ここはpre
</pre>
</body></html>
todo
これまた自分ではあまり使いませんが、dlタグ。
ulタグに習い、dlモード期間中は、字下げで区別するようにします。
preモードのように、モード期間中の最低の字下げ数を調べて、をれを基準に。
最低字下げ数の行はdtタグに。
そうでなければddタグに。
空行が出てくると、dtかddのタグを打ち直します。
v13.patch
diff -ur v12/ezmd.py v13/ezmd.py
--- v12/ezmd.py 2019-09-30 01:52:00.000000000 +0900
+++ v13/ezmd.py 2019-09-30 21:30:25.000000000 +0900
@@ -5,7 +5,7 @@
import nkf
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
-modes = heads + [ 'p', 'pre', 'ul', 'index' ]
+modes = heads + [ 'p', 'pre', 'ul', 'dl', 'index' ]
is_all_ge_n = lambda s, c, n: all( map( lambda c_: c_ == c, s ) ) and len(s) >= n
@@ -31,6 +31,7 @@
flat_map = lambda f, lst: sum( map( lambda o: to_lst( f(o) ), lst ), [] )
lst_strip = lambda lst: list( map( lambda s: s.strip(), lst ) )
+lst_to_empty = lambda lst: list( map( lambda s: '' if s.strip() == '' else s, lst ) )
strip_head = lambda s: strip_head(s[1:]) if s and s[0] in (' ', '\t') else s
strip_tail = lambda s: strip_tail(s[:-1]) if s and s[-1] in (' ', '\t') else s
@@ -142,6 +143,24 @@
res.extend( list( map(lst_to, lsts) ) )
+def do_mode_dl(buf, res):
+ buf = lst_to_empty(buf)
+ buf = cut_ht_empty(buf)
+ if buf:
+ buf = cut_verb_idt(buf)
+ (lst, mode, mbuf) = ( [], '', [] )
+ for s in buf:
+ mode_ = '' if s == '' else ( 'dd' if s[0] in (' ', '\t') else 'dt' )
+ if mode_ != mode:
+ if mode and mbuf:
+ lst.append( { mode: do_str(mbuf) } )
+ (mode, mbuf) = ( mode_, [ s.strip() ] )
+ elif s:
+ mbuf.append( s.strip() )
+ if mode and mbuf:
+ lst.append( { mode: do_str(mbuf) } )
+ res.append( { 'dl': lst } )
+
def do_mode(mode, buf, res, hd_names):
if mode in heads:
buf = lst_strip(buf)
@@ -174,6 +193,8 @@
res.append( { 'pre': s } )
elif mode == 'ul':
do_mode_ul(buf, res)
+ elif mode == 'dl':
+ do_mode_dl(buf, res)
elif mode == 'hr':
res.extend( [ { 'p': { 'hr': '/' } } ] * len(buf) )
elif mode == 'index':
$ cat v13.patch | patch -p1
確認用のデータ
$ diff -u foo_12.txt foo_13.txt --- foo_12.txt 2019-09-30 01:42:26.000000000 +0900 +++ foo_13.txt 2019-09-30 15:37:25.641863000 +0900 @@ -164,5 +164,40 @@ 改行を入れてみると 長い文字列\n「こんちには 世界(^_^)\nこんちには(^_^)\n世界(^_^)\nfoo=こんちには \nbar=世界(^_^)\nこんちには(^_^)\n世界(^_^)\nfoo=こんちには」\nの場合 +p + dlをためす + +dl + int + 整数 + float + 実数 + complex + 複素数 + +p +あるいは + +dl + +int + + 整数 + + 割込 + +float + + 実数 + + 浮遊 + (飲物の中のアイスクリーム?) + +complex + + 複素数 + + 劣等感 + pre ここはpre
実行してみます。
$ ./ezmd.py < foo_13.txt : - foo=こんちには」 - br: / - の場合 - p: - dlをためす - dl: - dt: - int - dd: - 整数 - dt: - float - dd: - 実数 - dt: - complex - p: - あるいは - dl: - dt: - int - dd: - 整数 - dd: - 割込 - dt: - float - dd: - 実数 - dd: - 浮遊 - (飲物の中のアイスクリーム?) - dt: - complex - dd: - 複素数 - pre: | ここはpre
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_13.txt > foo_13.html $ nkf -u foo_13.html : foo=こんちには」 <br> の場合</ul> <p>dlをためす</p> <dl><dt>int</dt> <dd>整数</dd> <dt>float</dt> <dd>実数</dd> <dt>complex</dt></dl> <p>あるいは</p> <dl><dt>int</dt> <dd>整数</dd> <dd>割込</dd> <dt>float</dt> <dd>実数</dd> <dd>浮遊 (飲物の中のアイスクリーム?)</dd> <dt>complex</dt> <dd>複素数</dd></dl> <pre>ここはpre :
:
あるいは
:
foo_13.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1><a name="c_1_0">Python2とPython3での日本語文字列対応について</a></h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回
<s>「うぅっ」</s>
「ぬはぁ」とうなってます。</p>
<p><hr></p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2: の場合</p>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul>
<p><hr></p>
<p>:4 の場合</p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2:3 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>2 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>3 の場合</p>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul>
<p><hr></p>
<h2><a name="c_2_1">結論</a></h2>
<h3><a name="c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a></h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<p>(改行を入れてみると)
Python2 では日本語を含む文字列は
<br>
.encode('utf-8')して UTF-8 で保持。</p>
<p>Python3
<br>
では日本語の有無に関係なく、
<br>
素直にstrのままでよし。
<br>
ここは改行の直後</p>
<h3><a name="c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a></h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので
<img src="beat.jpg">
注意。</p>
<p><hr></p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<p><a href="v2.patch">v2.patch</a></p>
<p>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。</p>
<p><a href="v2.patch">v2.patch</a>
と
<a href="v3.patch">v3.patch</a>
と
<a href="v4.patch">v4.patch</a></p>
<p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p>
<p>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li><a href="v2.patch">v2.patch</a>
<a href="v3.patch">v3.patch</a>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li><a href="v2.patch">v2.patch</a>
<a href="v3.patch">v3.patch</a></ul>
<li>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。
<li>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。
<li><img src="beat.jpg">
<li><video src="cut.mp4" controls playsinline></video></ul>
<p>ここはp</p>
<p>---</p>
<p><hr></p>
<p><hr></p>
<p>ここは暗黙のp</p>
<h3><a name="c_3_4">ここはh3---</a></h3>
<p><hr></p>
<p><hr></p>
<p>---</p>
<p>ここはp</p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li><s>データの文字列2つを</s>
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し
<li>長い文字列「こんちには 世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには bar=世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには」の場合
<li>改行を入れてみると
<li>長い文字列
<br>
「こんちには 世界(^_^)
<br>
こんちには(^_^)
<br>
世界(^_^)
<br>
foo=こんちには
<br>
bar=世界(^_^)
<br>
こんちには(^_^)
<br>
世界(^_^)
<br>
foo=こんちには」
<br>
の場合</ul>
<p>dlをためす</p>
<dl><dt>int</dt>
<dd>整数</dd>
<dt>float</dt>
<dd>実数</dd>
<dt>complex</dt></dl>
<p>あるいは</p>
<dl><dt>int</dt>
<dd>整数</dd>
<dd>割込</dd>
<dt>float</dt>
<dd>実数</dd>
<dd>浮遊
(飲物の中のアイスクリーム?)</dd>
<dt>complex</dt>
<dd>複素数</dd></dl>
<pre>ここはpre
</pre>
</body></html>
todo
tableタグ、全部サポートすると果てしなさそうなので、自分が使いそうな機能だけ対応してみます。
まだスタイルシートが定着して無い頃、 ページのレイアウトにtableタグが入れ子で使われるといった乱用がはびこっていたため、 個人的には、今だにtableタグにあまり良い印象はありません。
そんな事もあり、以前はtableタグに頼らずに
などと、テーブルをテキストで描画するツールを作り
SMFを読み込み音の波形データを作るプログラム (C言語) などで SMFの構造概略 などとpre タグで表示しておりました。
例えばこのように。
+--------+------------------+--------+-------------------------------------------------------------+ | 分類 | 種別 |データ長| 内容 | +--------+------------------+--------+-------------------------------------------------------------+ |ヘッダ |ID |4バイト |"MThd" アスキー・コード 'M','T','h','d' の 4バイト | | +------------------+--------+-------------------------------------------------------------+ | |サイズ |4バイト |以降のヘッダのバイト数をビッグエンディアンで格納 | | | | |ヘッダの場合は値6固定なので、00,00,00,06 の4バイト | | +------------------+--------+-------------------------------------------------------------+ | |フォーマットタイプ|2バイト |値0, 1, 2 のいづれかをビッグエンディアンで格納 | | | | |ここではフォーマットタイプ 0 の SMF のみ扱うので、 | | | | |00,00 の2バイト | | +------------------+--------+-------------------------------------------------------------+ | |トラック数 |2バイト |トラック数をビッグエンディアンで格納 | | | | |フォーマットタイプが0の場合は、トラック数は1固定なので、 | | | | |00,01 の2バイト | | +------------------+--------+-------------------------------------------------------------+ | |時間分解能 |2バイト |四分音符の分割数をビッグエンディアンで格納 | | | | |四分音符1つをここで指定した値で分割した長さが、時間の最小単位| | | | |ただし1バイト目の最上位ビットが'1'の場合は、別の扱いとなる | | | | |ここでは1バイト目の最上位ビットが'0'のSMFのみを扱う | +--------+------------------+--------+-------------------------------------------------------------+ |トラック|ID |4バイト |"MTrk" アスキー・コード 'M','T','r','k' の 4バイト | | +------------------+--------+-------------------------------------------------------------+ | |サイズ |4バイト |以降のトラックのバイト数をビッグエンディアンで格納 | | +------------------+--------+-------------------------------------------------------------+ | |デルタタイム |可変長 | | | +------------------+--------+-------------------------------------------------------------+ | |イベント |可変長 | | | +------------------+--------+-------------------------------------------------------------+ | |デルタタイム |可変長 | | | +------------------+--------+-------------------------------------------------------------+ | |イベント |可変長 | | | +------------------+--------+-------------------------------------------------------------+ | | : | | +------------------+--------+-------------------------------------------------------------+ | |デルタタイム |可変長 | | | +------------------+--------+-------------------------------------------------------------+ | |イベント |可変長 | | +--------+------------------+--------+-------------------------------------------------------------+
ですが、見ての通り末尾が揃いません。(T_T)
等幅フォントとはいえ、ASCIIのフォントと日本語のフォントの幅は異なります。
そして、ツールは日本語のフォントの幅が、ASCIIのフォントの幅の2倍になっている事を期待しています。
あきらめて、簡単な範囲でtableタグに対応しておきます。
できるだけシンプルに。
'tbl'だけの行でtblモードに。
tblモード中は
例えば
tbl foo|bar|hoge 1 |2 |3 4 |5 |6
で
foo | bar | hoge |
1 | 2 | 3 |
4 | 5 | 6 |
となるように。
横に長過ぎるテキストも何なので...
ul,liタグと同様に、行末が'\'の行は次行と結合の扱いとします。
例えば
tbl foo|bar|hoge aaaaaaaaaaaaaaaa | \ bbbbbbbbbbbbbbbb | \ cccccccccccccccc 4 |5 |6
で
foo | bar | hoge |
aaaaaaaaaaaaaaaa | bbbbbbbbbbbbbbbb | cccccccccccccccc |
4 | 5 | 6 |
となるように。
'\|' でエスケープします。
例えば
tbl foo|bar|hoge 1 |2\|-2|3 4 |5 |6\|7
で
foo | bar | hoge |
1 | 2|-2 | 3 |
4 | 5 | 6|7 |
となるように。
行の開始はデフォルトはtdタグですが、 タグの打ち直しのときに、 '|'の代わりに2つ連続の'||'を使って仕切ると、 以降thタグへと切り替わる事にします。
再度'||'で仕切るとtdタグに戻ります。
行の先頭や末尾に'|'をつけても無視しますが、 '||'で始まっている場合はthタグから開始となります。
例えば、行の先頭と末尾に'|'を追加して
tbl |foo|bar|hoge| |1 |2 |3 | |4 |5 |6 |
としても
foo | bar | hoge |
1 | 2 | 3 |
4 | 5 | 6 |
と変わらず。
ここで
tbl ||foo|bar|hoge| | 1 |2 |3 | | 4 |5 |6 |
などとすると
foo | bar | hoge |
---|---|---|
1 | 2 | 3 |
4 | 5 | 6 |
先頭行がこのようにthに。
さらに
tbl ||foo|bar|hoge| ||1 ||2 |3 | ||4 ||5 |6 |
などとすると
foo | bar | hoge |
---|---|---|
1 | 2 | 3 |
4 | 5 | 6 |
先頭のカラムもthに。
th, tdタグのcolspan, rowspanを指定できるようにします。
セルの仕切り '|' あるいは '||' の直後に、スペースを入れずに 'c'あるいは'r'の1文字が続き、 さらにスペースを入れずに10進文字列が続く場合に、 そのセルにcolspanあるいはrowspanの指定を追加します。
colspanかrowspanのどちらかしか指定できない仕様ですが、 まぁ自分としてはこれで十分という事で。
tbl ||foo |c2 bar|hoge| ||1 ||2 |3 |4 | ||r2 4||5 |6 |7 | | a |b |c | ||d ||e |f |g |
などとすると
foo | bar | hoge | |
---|---|---|---|
1 | 2 | 3 | 4 |
4 | 5 | 6 | 7 |
a | b | c | |
d | e | f | g |
このように。
pタグ、ulタグ、dlタグと同じ扱いで do_str() を使っているので、 a (href)タグのリンク、brタグの改行が使えるはずです。
tbl ||foo |c2 bar|hoge| ||1 ||2 |3 |4 | ||r2 4||5 |6 |7 | | a |b |c | ||d ||e |f |g | ||z || hoge\nfuga | [[v14.patch]] |\ [[http://kondoh.html.xdomain.jp/index.html \| トップページ ]] |
などとすると
foo | bar | hoge | |
---|---|---|---|
1 | 2 | 3 | 4 |
4 | 5 | 6 | 7 |
a | b | c | |
d | e | f | g |
z | hoge
fuga |
v14.patch | トップページ |
このように
v14.patch
diff -ur v13/ezmd.py v14/ezmd.py
--- v13/ezmd.py 2019-09-30 21:30:25.000000000 +0900
+++ v14/ezmd.py 2019-10-01 01:05:53.000000000 +0900
@@ -5,7 +5,7 @@
import nkf
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
-modes = heads + [ 'p', 'pre', 'ul', 'dl', 'index' ]
+modes = heads + [ 'p', 'pre', 'ul', 'dl', 'tbl', 'index' ]
is_all_ge_n = lambda s, c, n: all( map( lambda c_: c_ == c, s ) ) and len(s) >= n
@@ -161,6 +161,54 @@
lst.append( { mode: do_str(mbuf) } )
res.append( { 'dl': lst } )
+def do_tr(s):
+ tgl = lambda md, n: md if n == 1 else ('th' if md == 'td' else 'td')
+
+ def parse_bar(s, md):
+ i = 0
+ while True:
+ j = s_idx( s[i:], '|' )
+ i += j
+ if j < 0:
+ return [ (s, md) ]
+ if j == 0 or s[i-1] != '\\':
+ break
+ i += 1
+
+ n = 2 if s[i+1:i+2] == '|' else 1
+ return [ ( s[:i], md ) ] + parse_bar( s[i+n:], tgl(md, n) )
+
+ lst = parse_bar(s, 'td')
+
+ def split_num(s):
+ s1 = s[1:]
+ i = s_idx(s1, ' ')
+ (t, s_) = ( s1[:i], s1[i+1:] ) if i >= 0 else (s, '')
+ return (t, s_) if t.isdigit() else ('', s)
+
+ def th_td(s, md):
+ if not s:
+ return []
+ s = s.replace('\|', '|')
+ tag = md
+ if len(s) > 2 and s[0] in 'cr':
+ cr = 'col' if s[0] == 'c' else 'row'
+ (t, s) = split_num(s)
+ if t:
+ tag += ' {}span="{}"'.format(cr, t)
+ return { tag: do_str( s.strip() ) }
+
+ lst = flat_map( lambda s_md: th_td(*s_md), lst )
+ return { 'tr': lst }
+
+def do_mode_tbl(buf, res):
+ buf = esc_join(buf)
+ buf = lst_strip(buf)
+ buf = cut_empty(buf)
+ if buf:
+ tag = 'table border="1" cellspacing="0"'
+ res.append( { tag: list( map(do_tr, buf) ) } )
+
def do_mode(mode, buf, res, hd_names):
if mode in heads:
buf = lst_strip(buf)
@@ -195,6 +243,8 @@
do_mode_ul(buf, res)
elif mode == 'dl':
do_mode_dl(buf, res)
+ elif mode == 'tbl':
+ do_mode_tbl(buf, res)
elif mode == 'hr':
res.extend( [ { 'p': { 'hr': '/' } } ] * len(buf) )
elif mode == 'index':
$ cat v14.patch | patch -p1
確認用のデータ
$ diff -u foo_13.txt foo_14.txt --- foo_13.txt 2019-09-30 15:37:25.000000000 +0900 +++ foo_14.txt 2019-09-30 21:40:43.000000000 +0900 @@ -199,5 +199,48 @@ 劣等感 +p +table + +tbl + +foo|bar|hoge +1|2|3 +4|5|6 + +p +table th + +tbl +||foo|bar|hoge +1|2|3 +4|5|6 + +p +table th2 + +tbl +||foo||bar|hoge +||1||2|3 +||4||5|6 + +p +table colspan + +tbl + +||foo||c2 bar|hoge +||1||2|3|4 +||4||5|c2 6 + +p +table rowspan + +tbl + +||foo||r2 bar|hoge +||1||3 +||4||5|6 + pre ここはpre
実行してみます。
$ ./ezmd.py < foo_14.txt : - dd: - 劣等感 - p: - table - table border="1" cellspacing="0": - tr: - td: foo - td: bar - td: hoge - tr: - td: '1' - td: '2' - td: '3' - tr: - td: '4' - td: '5' - td: '6' - p: - table th - table border="1" cellspacing="0": - tr: - th: foo - th: bar - th: hoge - tr: - td: '1' - td: '2' - td: '3' - tr: - td: '4' - td: '5' - td: '6' - p: - table th2 - table border="1" cellspacing="0": - tr: - th: foo - td: bar - td: hoge - tr: - th: '1' - td: '2' - td: '3' - tr: - th: '4' - td: '5' - td: '6' - p: - table colspan - table border="1" cellspacing="0": - tr: - th: foo - td colspan="2": bar - td: hoge - tr: - th: '1' - td: '2' - td: '3' - td: '4' - tr: - th: '4' - td: '5' - td colspan="2": '6' - p: - table rowspan - table border="1" cellspacing="0": - tr: - th: foo - td rowspan="2": bar - td: hoge - tr: - th: '1' - td: '3' - tr: - th: '4' - td: '5' - td: '6' - pre: | ここはpre
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_14.txt > foo_14.html $ nkf -u foo_14.html : <dd>劣等感</dd></dl> <p>table</p> <table border="1" cellspacing="0"><tr><td>foo</td> <td>bar</td> <td>hoge</td></tr> <tr><td>1</td> <td>2</td> <td>3</td></tr> <tr><td>4</td> <td>5</td> <td>6</td></tr></table> <p>table th</p> <table border="1" cellspacing="0"><tr><th>foo</th> <th>bar</th> <th>hoge</th></tr> <tr><td>1</td> <td>2</td> <td>3</td></tr> <tr><td>4</td> <td>5</td> <td>6</td></tr></table> <p>table th2</p> <table border="1" cellspacing="0"><tr><th>foo</th> <td>bar</td> <td>hoge</td></tr> <tr><th>1</th> <td>2</td> <td>3</td></tr> <tr><th>4</th> <td>5</td> <td>6</td></tr></table> <p>table colspan</p> <table border="1" cellspacing="0"><tr><th>foo</th> <td colspan="2">bar</td> <td>hoge</td></tr> <tr><th>1</th> <td>2</td> <td>3</td> <td>4</td></tr> <tr><th>4</th> <td>5</td> <td colspan="2">6</td></tr></table> <p>table rowspan</p> <table border="1" cellspacing="0"><tr><th>foo</th> <td rowspan="2">bar</td> <td>hoge</td></tr> <tr><th>1</th> <td>3</td></tr> <tr><th>4</th> <td>5</td> <td>6</td></tr></table> <pre>ここはpre </pre> </body></html>
:
table
foo | bar | hoge |
1 | 2 | 3 |
4 | 5 | 6 |
table th
foo | bar | hoge |
---|---|---|
1 | 2 | 3 |
4 | 5 | 6 |
table th2
foo | bar | hoge |
---|---|---|
1 | 2 | 3 |
4 | 5 | 6 |
table colspan
foo | bar | hoge | |
---|---|---|---|
1 | 2 | 3 | 4 |
4 | 5 | 6 |
table rowspan
foo | bar | hoge |
---|---|---|
1 | 3 | |
4 | 5 | 6 |
:
foo_14.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1><a name="c_1_0">Python2とPython3での日本語文字列対応について</a></h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回
<s>「うぅっ」</s>
「ぬはぁ」とうなってます。</p>
<p><hr></p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2: の場合</p>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul>
<p><hr></p>
<p>:4 の場合</p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2:3 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>2 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>3 の場合</p>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul>
<p><hr></p>
<h2><a name="c_2_1">結論</a></h2>
<h3><a name="c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a></h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<p>(改行を入れてみると)
Python2 では日本語を含む文字列は
<br>
.encode('utf-8')して UTF-8 で保持。</p>
<p>Python3
<br>
では日本語の有無に関係なく、
<br>
素直にstrのままでよし。
<br>
ここは改行の直後</p>
<h3><a name="c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a></h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので
<img src="beat.jpg">
注意。</p>
<p><hr></p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<p><a href="v2.patch">v2.patch</a></p>
<p>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。</p>
<p><a href="v2.patch">v2.patch</a>
と
<a href="v3.patch">v3.patch</a>
と
<a href="v4.patch">v4.patch</a></p>
<p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p>
<p>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li><a href="v2.patch">v2.patch</a>
<a href="v3.patch">v3.patch</a>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li><a href="v2.patch">v2.patch</a>
<a href="v3.patch">v3.patch</a></ul>
<li>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。
<li>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。
<li><img src="beat.jpg">
<li><video src="cut.mp4" controls playsinline></video></ul>
<p>ここはp</p>
<p>---</p>
<p><hr></p>
<p><hr></p>
<p>ここは暗黙のp</p>
<h3><a name="c_3_4">ここはh3---</a></h3>
<p><hr></p>
<p><hr></p>
<p>---</p>
<p>ここはp</p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li><s>データの文字列2つを</s>
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し
<li>長い文字列「こんちには 世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには bar=世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには」の場合
<li>改行を入れてみると
<li>長い文字列
<br>
「こんちには 世界(^_^)
<br>
こんちには(^_^)
<br>
世界(^_^)
<br>
foo=こんちには
<br>
bar=世界(^_^)
<br>
こんちには(^_^)
<br>
世界(^_^)
<br>
foo=こんちには」
<br>
の場合</ul>
<p>dlをためす</p>
<dl><dt>int</dt>
<dd>整数</dd>
<dt>float</dt>
<dd>実数</dd>
<dt>complex</dt>
<dd>複素数</dd></dl>
<p>あるいは</p>
<dl><dt>int</dt>
<dd>整数</dd>
<dd>割込</dd>
<dt>float</dt>
<dd>実数</dd>
<dd>浮遊
(飲物の中のアイスクリーム?)</dd>
<dt>complex</dt>
<dd>複素数</dd>
<dd>劣等感</dd></dl>
<p>table</p>
<table border="1" cellspacing="0"><tr><td>foo</td>
<td>bar</td>
<td>hoge</td></tr>
<tr><td>1</td>
<td>2</td>
<td>3</td></tr>
<tr><td>4</td>
<td>5</td>
<td>6</td></tr></table>
<p>table th</p>
<table border="1" cellspacing="0"><tr><th>foo</th>
<th>bar</th>
<th>hoge</th></tr>
<tr><td>1</td>
<td>2</td>
<td>3</td></tr>
<tr><td>4</td>
<td>5</td>
<td>6</td></tr></table>
<p>table th2</p>
<table border="1" cellspacing="0"><tr><th>foo</th>
<td>bar</td>
<td>hoge</td></tr>
<tr><th>1</th>
<td>2</td>
<td>3</td></tr>
<tr><th>4</th>
<td>5</td>
<td>6</td></tr></table>
<p>table colspan</p>
<table border="1" cellspacing="0"><tr><th>foo</th>
<td colspan="2">bar</td>
<td>hoge</td></tr>
<tr><th>1</th>
<td>2</td>
<td>3</td>
<td>4</td></tr>
<tr><th>4</th>
<td>5</td>
<td colspan="2">6</td></tr></table>
<p>table rowspan</p>
<table border="1" cellspacing="0"><tr><th>foo</th>
<td rowspan="2">bar</td>
<td>hoge</td></tr>
<tr><th>1</th>
<td>3</td></tr>
<tr><th>4</th>
<td>5</td>
<td>6</td></tr></table>
<pre>ここはpre
</pre>
</body></html>
todo
ulのリストからtableへ変換を少し試してみてたのですが、、、
本ezmd.pyが出力するYAML形式は、 簡易なHTMLパーサ 2018秋 が受け付けるける形式です。
基本的に辞書のリストですが、 辞書の長さは1に限定し、タグのプロパティ情報は辞書のキーの文字列に含めています。
この冗長というか特殊な形式に従って、内部でタグ情報を保持しているので、 プログラムからタグのプロパティ情報を変更しようとすると、面倒で骨が折れます。
tag_new(name, prop, v)
を導入して、空クラスをベースにしたクラスインスタンスに置き換える事にします。
自分が多用する空クラスのスタイルについては クロージャと空クラス を参照
そして最後にYAML形式でdumpする直前に、 これまでと同じ形式にまとめて変換するようにしました。
v15.patch
diff -ur v14/ezmd.py v15/ezmd.py
--- v14/ezmd.py 2019-10-01 01:05:53.000000000 +0900
+++ v15/ezmd.py 2019-10-02 03:11:30.000000000 +0900
@@ -26,6 +26,32 @@
return (s, mode)
+class Empty:
+ def __init__(self, dic={}):
+ self.to_attr(dic)
+
+ def to_attr(self, dic):
+ for (k, v) in dic.items():
+ setattr(self, k, v)
+ return self
+
+def tag_new(name, prop, v):
+ return Empty( locals() )
+
+def tag_to_dic(tag):
+ pstr = lambda k, v: '{}="{}"'.format(k, v) if v != None else k
+ lst = [ tag.name ] + list( map( lambda kv: pstr(*kv), tag.prop.items() ) )
+ k = ' '.join(lst)
+
+ def v_get(v):
+ if type(v) == list:
+ return list( map(v_get, v) )
+ if isinstance(v, Empty):
+ return tag_to_dic(v)
+ return v
+
+ return { k: v_get(tag.v) }
+
to_lst = lambda o: o if type(o) == list else [o]
from_lst = lambda lst: lst[0] if len(lst) == 1 else lst
flat_map = lambda f, lst: sum( map( lambda o: to_lst( f(o) ), lst ), [] )
@@ -66,17 +92,17 @@
def do_v1v2(v1, v2):
if v1 == 'img':
- return { 'img src="{}"'.format(v2): '/' }
+ return tag_new('img', {'src': v2}, '/')
if v1 == 'video':
- return { 'video src="{}" controls playsinline'.format(v2): '' }
+ return tag_new('video', {'src': v2, 'controls': None, 'playsinline': None}, '')
if v1 == '-':
- return { 's': v2 }
- return { 'a href="{}"'.format(v1): v2 } if v1 else v2
+ return tag_new('s', {}, v2)
+ return tag_new('a', {'href': v1}, v2) if v1 else v2
def do_br(s):
p = '\\n'
if p in s:
- lst = flat_map( lambda s_: [ s_, { 'br': '/' } ], s.split(p) )[:-1]
+ lst = flat_map( lambda s_: [ s_, tag_new('br', {}, '/') ], s.split(p) )[:-1]
return from_lst( cut_empty(lst) )
return s
@@ -99,7 +125,7 @@
# sol : str or lst
#
def map_sol(f_s_ret_sol, sol):
- f = lambda o: o if type(o) == dict else f_s_ret_sol(o)
+ f = lambda o: o if isinstance(o, Empty) else f_s_ret_sol(o)
return flat_map(f, sol) if type(sol) == list else f_s_ret_sol(sol)
def do_str(sol): # str or list
@@ -137,9 +163,9 @@
list( map(buf_to_stk_lsts, buf) ) # make lists
def lst_to(lst):
- f = lambda o: lst_to(o) if type(o) == list else {'li /': do_str(o) }
+ f = lambda o: lst_to(o) if type(o) == list else tag_new( 'li', {'/': None}, do_str(o) )
lst = list( map(f, lst) )
- return { 'ul': lst }
+ return tag_new('ul', {}, lst)
res.extend( list( map(lst_to, lsts) ) )
@@ -153,13 +179,13 @@
mode_ = '' if s == '' else ( 'dd' if s[0] in (' ', '\t') else 'dt' )
if mode_ != mode:
if mode and mbuf:
- lst.append( { mode: do_str(mbuf) } )
+ lst.append( tag_new( mode, {}, do_str(mbuf) ) )
(mode, mbuf) = ( mode_, [ s.strip() ] )
elif s:
mbuf.append( s.strip() )
if mode and mbuf:
- lst.append( { mode: do_str(mbuf) } )
- res.append( { 'dl': lst } )
+ lst.append( tag_new( mode, {}, do_str(mbuf) ) )
+ res.append( tag_new('dl', {}, lst) )
def do_tr(s):
tgl = lambda md, n: md if n == 1 else ('th' if md == 'td' else 'td')
@@ -190,24 +216,25 @@
if not s:
return []
s = s.replace('\|', '|')
- tag = md
+ prop = {}
if len(s) > 2 and s[0] in 'cr':
cr = 'col' if s[0] == 'c' else 'row'
(t, s) = split_num(s)
if t:
- tag += ' {}span="{}"'.format(cr, t)
- return { tag: do_str( s.strip() ) }
+ prop[ '{}span'.format(cr) ] = int(t)
+ return tag_new( md, prop, do_str( s.strip() ) )
lst = flat_map( lambda s_md: th_td(*s_md), lst )
- return { 'tr': lst }
+ return tag_new('tr', {}, lst)
def do_mode_tbl(buf, res):
buf = esc_join(buf)
buf = lst_strip(buf)
buf = cut_empty(buf)
if buf:
- tag = 'table border="1" cellspacing="0"'
- res.append( { tag: list( map(do_tr, buf) ) } )
+ prop = {'border': 1, 'cellspacing': 0}
+ v = list( map(do_tr, buf) )
+ res.append( tag_new('table', prop, v) )
def do_mode(mode, buf, res, hd_names):
if mode in heads:
@@ -216,7 +243,7 @@
s = ''.join(buf)
(h_i, n) = ( int(mode[1:]), len(hd_names) )
name = 'c_{}_{}'.format(h_i, n)
- res.append( { mode: { 'a name="{}"'.format(name): s } } )
+ res.append( tag_new( mode, {}, tag_new('a', {'name': name}, s) ) )
hd_names.append( (h_i, n, name, s) )
elif mode == 'p':
@@ -232,13 +259,13 @@
lst = []
for lst in lsts:
lst = flat_map(do_str, lst)
- res.append( { 'p': lst } )
+ res.append( tag_new('p', {}, lst) )
elif mode == 'pre':
buf = cut_ht_empty(buf)
if buf:
buf = cut_verb_idt(buf)
s = '\n'.join(buf) + '\n'
- res.append( { 'pre': s } )
+ res.append( tag_new('pre', {}, s) )
elif mode == 'ul':
do_mode_ul(buf, res)
elif mode == 'dl':
@@ -246,11 +273,11 @@
elif mode == 'tbl':
do_mode_tbl(buf, res)
elif mode == 'hr':
- res.extend( [ { 'p': { 'hr': '/' } } ] * len(buf) )
+ res.extend( [ tag_new('p', {}, tag_new('hr', {}, '/') ) ] * len(buf) )
elif mode == 'index':
buf = lst_strip(buf)
buf = cut_empty(buf)
- res.append( { 'index': buf } ) # continue to 2 pass
+ res.append( tag_new('index', {}, buf) ) # continue to 2 pass
def do_index(lst, hd_names):
@@ -283,7 +310,7 @@
do_mode_ul(buf, ul_res)
return ul_res
- return flat_map( lambda d: f( d.get('index') ) if 'index' in d else d, lst )
+ return flat_map( lambda tag: f(tag.v) if tag.name == 'index' else tag, lst )
def ezmd(lst):
lst = ['p'] + lst
@@ -319,6 +346,7 @@
lst = list( map( strip_tail, lst ) )
lst = ezmd(lst)
+ lst = list( map( tag_to_dic, lst ) )
u8 = yaml_dump(lst)
b = nkf.cvt(u8, nkf_opt) if nkf_opt != '-u' else u8
$ cat v15.patch | patch -p1
これまでのテキストデータで確認してみます。
$ ./to_html.py foo_head.yaml foo_14.txt | diff -u foo_14.html - $ $ ./to_html.py head.yaml index.ez.txt ezmd | diff -u index.ez.html - $
OK
propを辞書にしたので、 プロパティ指定の順番が変わる可能性がありましたが、 運良く一致してます。(^_^)v
todo
次の一手を容易にするため、もうちょっと整理しておきます。
このパターンの処理。
buf_loop_new(buf, is_call, func)
にまとめてみました。
仕様はそのままですが、解りにくそうな実装だったので、 再帰を使って書き直してみました。
(解り易すくなったかどうか疑問ですが...)
v16.patch
diff -ur v15/ezmd.py v16/ezmd.py
--- v15/ezmd.py 2019-10-02 03:11:30.000000000 +0900
+++ v16/ezmd.py 2019-10-02 04:11:00.000000000 +0900
@@ -78,15 +78,31 @@
cut_t_empty = lambda lst: cut_t_empty(lst[:-1]) if lst and lst[-1] == '' else lst
cut_ht_empty = lambda lst: cut_t_empty( cut_h_empty(lst) )
+def buf_loop_new(buf, is_call, func):
+ e = Empty()
+ e.mode = e.next_mode = None
+ e.tmp = []
+
+ def run():
+ for e.s in buf:
+ if is_call(e):
+ func(e)
+ e.tmp = []
+ e.mode = e.next_mode
+
+ if e.s != None:
+ e.tmp.append(e.s)
+ func(e)
+
+ return e.to_attr( locals() )
+
def esc_join(lst):
- res = []
- for s in lst:
- if res and res[-1] and res[-1][-1] == '\\':
- t = res[-1][:-1]
- res[-1] = strip_tail(t) + strip_head(s)
- else:
- res.append(s)
- return res
+ if len(lst) < 2:
+ return lst
+ if lst[0] and lst[0][-1] == '\\':
+ lst = [ strip_tail( lst[0][:-1] ) + strip_head( lst[1] ) ] + lst[2:]
+ return esc_join(lst)
+ return lst[:1] + esc_join( lst[1:] )
s_idx = lambda s, p, dv=-1: s.index(p) if p in s else dv
@@ -174,17 +190,20 @@
buf = cut_ht_empty(buf)
if buf:
buf = cut_verb_idt(buf)
- (lst, mode, mbuf) = ( [], '', [] )
- for s in buf:
- mode_ = '' if s == '' else ( 'dd' if s[0] in (' ', '\t') else 'dt' )
- if mode_ != mode:
- if mode and mbuf:
- lst.append( tag_new( mode, {}, do_str(mbuf) ) )
- (mode, mbuf) = ( mode_, [ s.strip() ] )
- elif s:
- mbuf.append( s.strip() )
- if mode and mbuf:
- lst.append( tag_new( mode, {}, do_str(mbuf) ) )
+ lst = []
+
+ def is_call(e):
+ e.next_mode = '' if e.s == '' else ( 'dd' if e.s[0] in (' ', '\t') else 'dt' )
+ e.s = e.s.strip()
+ return e.next_mode != e.mode
+
+ def func(e):
+ if e.mode and e.tmp:
+ lst.append( tag_new( e.mode, {}, do_str(e.tmp) ) )
+
+ e = buf_loop_new(buf, is_call, func)
+ e.run()
+
res.append( tag_new('dl', {}, lst) )
def do_tr(s):
@@ -315,16 +334,16 @@
def ezmd(lst):
lst = ['p'] + lst
(buf, res, hd_names) = ( [], [], [] )
- mode = ''
- while lst:
- s = lst.pop(0)
- (s, nmd) = next_mode_switch(s, mode);
- if nmd != mode:
- do_mode(mode, buf, res, hd_names)
- (mode, buf) = (nmd, [])
- if s != None:
- buf.append(s)
- do_mode(mode, buf, res, hd_names)
+
+ def is_call(e):
+ (e.s, e.next_mode) = next_mode_switch(e.s, e.mode)
+ return e.next_mode != e.mode
+
+ func = lambda e: do_mode(e.mode, e.tmp, res, hd_names)
+
+ e = buf_loop_new(lst, is_call, func)
+ e.run()
+
res = do_index(res, hd_names)
return res
$ cat v16.patch | patch -p1
確認を。
$ ./to_html.py head.yaml index.ez.txt ezmd | diff -u index.ez.html - $ $ ./to_html.py foo_head.yaml foo_14.txt | diff -u foo_14.html - | nkf -u : <li><img src="beat.jpg"> -<li><video src="cut.mp4" controls playsinline></video></ul> +<li><video src="cut.mp4" playsinline controls></video></ul> <p>ここはp</p> : <p>table rowspan</p> -<table border="1" cellspacing="0"><tr><th>foo</th> +<table cellspacing="0" border="1"><tr><th>foo</th> <td rowspan="2">bar</td> <td>hoge</td></tr> <tr><th>1</th>
前回は完全一致でしたが、今回はプロパティの指定順が変わってしまいました。
辞書の順番は変わり得るのでOK
大分類、中分類、小分類の3階層くらいの箇条書の内容を「表」にしたもの。
良く見かけます。
例えば
箇条書
表になると
挨拶 | 朝 | おはよう |
ちいーっす | ||
昼 | こんにちは | |
ちいーっす | ||
夜 | こんばんわ | |
ちいーっす | ||
出発 | 出 | いってきます |
ほな | ||
送 | いってらっしゃい | |
帰宅 | 帰 | ただいま |
ただいまもどりました | ||
迎 | おかえり | |
おかえりあそばせ |
前者のままで良い気もするのですが、
見栄えにこだわって、何でもエクセルで表にする悪しき文化の影響なのか、何なのか...
前者のソースは
ul 挨拶 朝 おはよう ちぃーっす 昼 こんにちは ちぃーっす 夜 こんばんわ ちぃーっす 出発 出 いってきます ほな 送 いってらっしゃい 帰宅 帰 ただいま ただいまもどりました 迎 おかえり おかえりあそばせ
すなおな木構造。
それに対し後者は
tbl |r6 挨拶 |r2 朝 | おはよう | ちいーっす |r2 昼 | こんにちは | ちいーっす |r2 夜 | こんばんわ | ちいーっす |r3 出発 |r2 出 | いってきます | ほな | 送 | いってらっしゃい |r4 帰宅 |r2 帰 | ただいま | ただいまもどりました |r2 迎 | おかえり | おかえりあそばせ
セルの行方向の結合rowspanに相当する'|r値'の箇所の調整が、えぐいです。
こういうややこしい事は機械に任せるべきでしょう。
tblモードの中で、ulモードの形式を扱えるように対応してみます。
tblモード中に
の2つのローカル・モードを設けます。
特に指定がなければ、従来通りのテーブル・オリジナル・モード。
文字列 "tbl_ul" だけの行が現れると、以降はテーブル・ulモード。
テーブル・ulモードでは、ulモードの形式を受け付けます。
文字列 "tbl_org" だけの行が現れると、以降はテーブル・オリジナル・モードに戻ります。
tbl_orgやtbl_ulを行き来した結果の複数の表は、 結合して1つの表にまとめるようにします。
v17.patch
diff -ur v16/ezmd.py v17/ezmd.py
--- v16/ezmd.py 2019-10-02 04:11:00.000000000 +0900
+++ v17/ezmd.py 2019-10-02 20:42:54.000000000 +0900
@@ -246,14 +246,126 @@
lst = flat_map( lambda s_md: th_td(*s_md), lst )
return tag_new('tr', {}, lst)
-def do_mode_tbl(buf, res):
+tbl_prop = { 'border': 1, 'cellspacing': 0 }
+
+def do_tbl_org(buf, res):
buf = esc_join(buf)
buf = lst_strip(buf)
buf = cut_empty(buf)
if buf:
- prop = {'border': 1, 'cellspacing': 0}
v = list( map(do_tr, buf) )
- res.append( tag_new('table', prop, v) )
+ res.append( tag_new('table', tbl_prop, v) )
+
+def ul_to_tbl(ul):
+ def pack_ul(ul):
+ (lst, last) = ([], None)
+ for tag in ul.v:
+ if tag.name == 'li':
+ last = tag
+ lst.append(tag)
+ elif tag.name == 'ul' and last:
+ pack_ul(tag)
+ last.prop['sub_ul'] = tag
+ ul.v = lst
+
+ pack_ul(ul)
+
+ def sz_get(tag):
+ if tag.name == 'li':
+ k = 'sub_ul'
+ (w, h) = sz_get( tag.prop.get(k) ) if k in tag.prop else (0, 1)
+ return ( w + 1, max(h, 1) )
+ if tag.name == 'ul':
+ (ws, hs) = zip( *map(sz_get, tag.v) )
+ return ( max(ws), sum(hs) )
+ return (0, 0)
+
+ (gw, gh) = sz_get(ul)
+
+ def cv_to_tbl(tag, x, tbl):
+ if tag.name == 'ul':
+ for tag_ in tag.v:
+ cv_to_tbl(tag_, x, tbl)
+ elif tag.name == 'li':
+ prop = {}
+ tr = tbl.v[-1]
+ tr.v.append( tag_new('td', prop, tag.v) )
+
+ (w, h) = sz_get(tag)
+ if h > 1:
+ prop['rowspan'] = h
+
+ k = 'sub_ul'
+ if k in tag.prop:
+ cv_to_tbl( tag.prop.get(k), x+1, tbl )
+ else:
+ w = w - x + 1
+ if w > 1:
+ prop['colspan'] = w
+ tbl.v.append( tag_new('tr', {}, []) )
+
+ trs = [ tag_new('tr', {}, []) ]
+ tbl = tag_new( 'table', tbl_prop, trs )
+
+ cv_to_tbl(ul, 0, tbl)
+
+ if trs[-1].v == []:
+ trs.pop()
+ return tbl
+
+def do_tbl_ul(buf, res):
+ uls = []
+ do_mode_ul(buf, uls)
+ for ul in uls:
+ res.append( ul_to_tbl(ul) )
+
+def tbls_join(tbls):
+ def w_get(tag):
+ if tag.name in ('th', 'td'):
+ return tag.prop.get('colspan', 1)
+ if tag.name == 'tr':
+ return sum( map(w_get, tag.v) )
+ if tag.name == 'table':
+ return max( map(w_get, tag.v) )
+ return 0
+
+ w_max = max( map(w_get, tbls) )
+
+ trs = []
+ for tbl in tbls:
+ for tr in tbl.v:
+ add = w_max - w_get(tr)
+ tail = tr.v[-1]
+ k = 'colspan'
+ w = tail.prop.get(k, 1) + add
+ if w > 1:
+ tail.prop[k] = w
+ trs.append(tr)
+
+ prop = tbls[0].prop
+ return tag_new('table', prop, trs)
+
+def do_mode_tbl(buf, res):
+ res_ = []
+
+ def is_call(e):
+ if e.s in ('tbl_org', 'tbl_ul'):
+ e.next_mode = e.s # ok
+ e.s = None
+ return e.next_mode != e.mode
+ return False
+
+ def func(e):
+ if e.mode == 'tbl_org':
+ do_tbl_org(e.tmp, res_)
+ elif e.mode == 'tbl_ul':
+ do_tbl_ul(e.tmp, res_)
+
+ e = buf_loop_new(buf, is_call, func)
+ e.mode = 'tbl_org'
+ e.run()
+
+ res.append( tbls_join(res_) )
def do_mode(mode, buf, res, hd_names):
if mode in heads:
$ cat v17.patch | patch -p1
$ diff -u foo_14.txt foo_17.txt --- foo_14.txt 2019-09-30 21:40:43.000000000 +0900 +++ foo_17.txt 2019-10-02 15:21:09.963512000 +0900 @@ -242,5 +242,111 @@ ||1||3 ||4||5|6 +p +箇条書 + +ul + 挨拶 + 朝 + おはよう + ちぃーっす + 昼 + こんにちは + ちぃーっす + 夜 + こんばんわ + ちぃーっす + 出発 + 出 + いってきます + ほな + 送 + いってらっしゃい + 帰宅 + 帰 + ただいま + ただいまもどりました + 迎 + おかえり + おかえりあそばせ + +p +表 + +tbl + |r6 挨拶 |r2 朝 | おはよう + | ちいーっす + |r2 昼 | こんにちは + | ちいーっす + |r2 夜 | こんばんわ + | ちいーっす + |r3 出発 |r2 出 | いってきます + | ほな + | 送 | いってらっしゃい + |r4 帰宅 |r2 帰 | ただいま + | ただいまもどりました + |r2 迎 | おかえり + | おかえりあそばせ + +p + tbl_ulモード + +tbl +tbl_ul + 挨拶 + 朝 + おはよう + ちぃーっす + 昼 + こんにちは + ちぃーっす + 夜 + こんばんわ + ちぃーっす + 出発 + 出 + いってきます + ほな + 送 + いってらっしゃい + 帰宅 + 帰 + ただいま + ただいまもどりました + 迎 + おかえり + おかえりあそばせ + +p + tbl_orgとtbl_ulの結合 + +tbl + ||種別|状況|セリフ + +tbl_ul + 挨拶 + 朝 + おはよう + ちぃーっす + 昼 + こんにちは + ちぃーっす + 夜 + こんばんわ + ちぃーっす + 出発 + 出 + いってきます + ほな + 送 + いってらっしゃい + 帰宅 + 帰 + ただいま + ただいまもどりました + 迎 + おかえり + おかえりあそばせ + pre ここはpre
実行してみます。
$ ./ezmd.py < foo_17.txt : - p: - 箇条書 - ul: - li /: 挨拶 - ul: - li /: 朝 - ul: - li /: おはよう - li /: ちぃーっす - li /: 昼 - ul: - li /: こんにちは - li /: ちぃーっす - li /: 夜 - ul: - li /: こんばんわ - li /: ちぃーっす - li /: 出発 - ul: - li /: 出 - ul: - li /: いってきます - li /: ほな - li /: 送 - ul: - li /: いってらっしゃい - li /: 帰宅 - ul: - li /: 帰 - ul: - li /: ただいま - li /: ただいまもどりました - li /: 迎 - ul: - li /: おかえり - li /: おかえりあそばせ - p: - 表 - table cellspacing="0" border="1": - tr: - td rowspan="6": 挨拶 - td rowspan="2": 朝 - td: おはよう - tr: - td colspan="3": ちいーっす - tr: - td rowspan="2": 昼 - td colspan="2": こんにちは - tr: - td colspan="3": ちいーっす - tr: - td rowspan="2": 夜 - td colspan="2": こんばんわ - tr: - td colspan="3": ちいーっす - tr: - td rowspan="3": 出発 - td rowspan="2": 出 - td: いってきます - tr: - td colspan="3": ほな - tr: - td: 送 - td colspan="2": いってらっしゃい - tr: - td rowspan="4": 帰宅 - td rowspan="2": 帰 - td: ただいま - tr: - td colspan="3": ただいまもどりました - tr: - td rowspan="2": 迎 - td colspan="2": おかえり - tr: - td colspan="3": おかえりあそばせ - p: - tbl_ulモード - table cellspacing="0" border="1": - tr: - td rowspan="6": 挨拶 - td rowspan="2": 朝 - td: おはよう - tr: - td colspan="3": ちぃーっす - tr: - td rowspan="2": 昼 - td colspan="2": こんにちは - tr: - td colspan="3": ちぃーっす - tr: - td rowspan="2": 夜 - td colspan="2": こんばんわ - tr: - td colspan="3": ちぃーっす - tr: - td rowspan="3": 出発 - td rowspan="2": 出 - td: いってきます - tr: - td colspan="3": ほな - tr: - td: 送 - td colspan="2": いってらっしゃい - tr: - td rowspan="4": 帰宅 - td rowspan="2": 帰 - td: ただいま - tr: - td colspan="3": ただいまもどりました - tr: - td rowspan="2": 迎 - td colspan="2": おかえり - tr: - td colspan="3": おかえりあそばせ - p: - tbl_orgとtbl_ulの結合 - table cellspacing="0" border="1": - tr: - th: 種別 - th: 状況 - th: セリフ - tr: - td rowspan="6": 挨拶 - td rowspan="2": 朝 - td: おはよう - tr: - td colspan="3": ちぃーっす - tr: - td rowspan="2": 昼 - td colspan="2": こんにちは - tr: - td colspan="3": ちぃーっす - tr: - td rowspan="2": 夜 - td colspan="2": こんばんわ - tr: - td colspan="3": ちぃーっす - tr: - td rowspan="3": 出発 - td rowspan="2": 出 - td: いってきます - tr: - td colspan="3": ほな - tr: - td: 送 - td colspan="2": いってらっしゃい - tr: - td rowspan="4": 帰宅 - td rowspan="2": 帰 - td: ただいま - tr: - td colspan="3": ただいまもどりました - tr: - td rowspan="2": 迎 - td colspan="2": おかえり - tr: - td colspan="3": おかえりあそばせ - pre: | ここはpre
確かにソースのテキストが
+p +表 + +tbl + |r6 挨拶 |r2 朝 | おはよう + | ちいーっす + |r2 昼 | こんにちは + | ちいーっす + |r2 夜 | こんばんわ + | ちいーっす + |r3 出発 |r2 出 | いってきます + | ほな + | 送 | いってらっしゃい + |r4 帰宅 |r2 帰 | ただいま + | ただいまもどりました + |r2 迎 | おかえり + | おかえりあそばせ
のときの出力箇所
- p: - 表 - table cellspacing="0" border="1": - tr: - td rowspan="6": 挨拶 - td rowspan="2": 朝 - td: おはよう - tr: - td colspan="3": ちいーっす - tr: - td rowspan="2": 昼 - td colspan="2": こんにちは - tr: - td colspan="3": ちいーっす - tr: - td rowspan="2": 夜 - td colspan="2": こんばんわ - tr: - td colspan="3": ちいーっす - tr: - td rowspan="3": 出発 - td rowspan="2": 出 - td: いってきます - tr: - td colspan="3": ほな - tr: - td: 送 - td colspan="2": いってらっしゃい - tr: - td rowspan="4": 帰宅 - td rowspan="2": 帰 - td: ただいま - tr: - td colspan="3": ただいまもどりました - tr: - td rowspan="2": 迎 - td colspan="2": おかえり - tr: - td colspan="3": おかえりあそばせ
と
+p + tbl_ulモード + +tbl +tbl_ul + 挨拶 + 朝 + おはよう + ちぃーっす + 昼 + こんにちは + ちぃーっす + 夜 + こんばんわ + ちぃーっす + 出発 + 出 + いってきます + ほな + 送 + いってらっしゃい + 帰宅 + 帰 + ただいま + ただいまもどりました + 迎 + おかえり + おかえりあそばせ
のときの出力箇所
- p: - tbl_ulモード - table cellspacing="0" border="1": - tr: - td rowspan="6": 挨拶 - td rowspan="2": 朝 - td: おはよう - tr: - td colspan="3": ちぃーっす - tr: - td rowspan="2": 昼 - td colspan="2": こんにちは - tr: - td colspan="3": ちぃーっす - tr: - td rowspan="2": 夜 - td colspan="2": こんばんわ - tr: - td colspan="3": ちぃーっす - tr: - td rowspan="3": 出発 - td rowspan="2": 出 - td: いってきます - tr: - td colspan="3": ほな - tr: - td: 送 - td colspan="2": いってらっしゃい - tr: - td rowspan="4": 帰宅 - td rowspan="2": 帰 - td: ただいま - tr: - td colspan="3": ただいまもどりました - tr: - td rowspan="2": 迎 - td colspan="2": おかえり - tr: - td colspan="3": おかえりあそばせ
一致してます。OK
$ ./to_html.py foo_head.yaml foo_17.txt > foo_17.html $ cat foo_17.html | nkf -u : <p>箇条書</p> <ul><li>挨拶 <ul><li>朝 <ul><li>おはよう <li>ちぃーっす</ul> <li>昼 : <td colspan="2">おかえり</td></tr> <tr><td colspan="3">おかえりあそばせ</td></tr></table> <pre>ここはpre </pre> </body></html>
:
tbl_orgとtbl_ulの結合
種別 | 状況 | セリフ |
---|---|---|
挨拶 | 朝 | おはよう |
ちぃーっす | ||
昼 | こんにちは | |
ちぃーっす | ||
夜 | こんばんわ | |
ちぃーっす | ||
出発 | 出 | いってきます |
ほな | ||
送 | いってらっしゃい | |
帰宅 | 帰 | ただいま |
ただいまもどりました | ||
迎 | おかえり | |
おかえりあそばせ |
:
foo_17.html
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>py23str</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style>
</head><body>
<h1><a name="c_1_0">Python2とPython3での日本語文字列対応について</a></h1>
<p>毎回、同じようにつまづいて、同じような感じで対応してます。</p>
<p>なので、いいかげん自分に判りやすいようにまとめておきます。</p>
<p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p>
<p>データはYAML形式のファイルで用意。</p>
<p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、
毎回
<s>「うぅっ」</s>
「ぬはぁ」とうなってます。</p>
<p><hr></p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2: の場合</p>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul>
<p><hr></p>
<p>:4 の場合</p>
<ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a>
<ul><li><a href="#c_2_1">結論</a>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul></ul></ul>
<p><hr></p>
<p>2:3 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>2 の場合</p>
<ul><li><a href="#c_2_1">結論</a></ul>
<p><hr></p>
<p>3 の場合</p>
<ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a>
<li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a>
<li><a href="#c_3_4">ここはh3---</a></ul>
<p><hr></p>
<h2><a name="c_2_1">結論</a></h2>
<h3><a name="c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a></h3>
<p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p>
<p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p>
<p>(改行を入れてみると)
Python2 では日本語を含む文字列は
<br>
.encode('utf-8')して UTF-8 で保持。</p>
<p>Python3
<br>
では日本語の有無に関係なく、
<br>
素直にstrのままでよし。
<br>
ここは改行の直後</p>
<h3><a name="c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a></h3>
<p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p>
<p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p>
<p>Python2 の世界には .buffer は存在しないので
<img src="beat.jpg">
注意。</p>
<p><hr></p>
<pre>$ cat p2.py
#!/usr/bin/env python2
import sys
import yaml
if __name__ == "__main__":
s = sys.stdin.read()
d = yaml.load(s)
foo = d.get('foo')
bar = d.get('bar')
d['hoge'] = foo + ' ' + bar
d['fuga'] = 'foo={} bar={}'.format(foo, bar)
d['guha'] = '(^_^)'.join( d.values() )
s = yaml.dump(d, default_flow_style=False)
sys.stdout.write(s)
# EOF
</pre>
<p>ここはデフォルトp</p>
<p>ここは明示的にp</p>
<p><a href="v2.patch">v2.patch</a></p>
<p>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。</p>
<p><a href="v2.patch">v2.patch</a>
と
<a href="v3.patch">v3.patch</a>
と
<a href="v4.patch">v4.patch</a></p>
<p><a href="http://kondoh.html.xdomain.jp/ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></p>
<p>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。</p>
<pre>ここはpre
p
ここもpre
h1
ここもpre
</pre>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li><a href="v2.patch">v2.patch</a>
<a href="v3.patch">v3.patch</a>
<ul><li><a href="v2.patch">v2.patch</a>
<li><a href="v3.patch">v3.patch</a>
<li><a href="v2.patch">v2.patch</a>
<a href="v3.patch">v3.patch</a></ul>
<li>バージョン2のための
<a href="v2.patch">パッチ</a>
となります。
<li>これは
<a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import">pythonのモジュールのインポート</a>
について。
<li><img src="beat.jpg">
<li><video src="cut.mp4" playsinline controls></video></ul>
<p>ここはp</p>
<p>---</p>
<p><hr></p>
<p><hr></p>
<p>ここは暗黙のp</p>
<h3><a name="c_3_4">ここはh3---</a></h3>
<p><hr></p>
<p><hr></p>
<p>---</p>
<p>ここはp</p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" playsinline controls></video></p>
<ul><li>標準入力からYAML形式のテキストを読み込み
<li>yaml.load()でテキストをデータに
<li><s>データの文字列2つを</s>
<li>ごにょごにょいじって
<ul><li>foo + ' ' + bar
<li>.format()
<li>.join()</ul>
<li>yaml.dump()でデータをYAML形式のテキストにして
<li>標準出力に書き出し
<li>長い文字列「こんちには 世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには bar=世界(^_^)こんちには(^_^)世界(^_^)foo=こんちには」の場合
<li>改行を入れてみると
<li>長い文字列
<br>
「こんちには 世界(^_^)
<br>
こんちには(^_^)
<br>
世界(^_^)
<br>
foo=こんちには
<br>
bar=世界(^_^)
<br>
こんちには(^_^)
<br>
世界(^_^)
<br>
foo=こんちには」
<br>
の場合</ul>
<p>dlをためす</p>
<dl><dt>int</dt>
<dd>整数</dd>
<dt>float</dt>
<dd>実数</dd>
<dt>complex</dt>
<dd>複素数</dd></dl>
<p>あるいは</p>
<dl><dt>int</dt>
<dd>整数</dd>
<dd>割込</dd>
<dt>float</dt>
<dd>実数</dd>
<dd>浮遊
(飲物の中のアイスクリーム?)</dd>
<dt>complex</dt>
<dd>複素数</dd>
<dd>劣等感</dd></dl>
<p>table</p>
<table cellspacing="0" border="1"><tr><td>foo</td>
<td>bar</td>
<td>hoge</td></tr>
<tr><td>1</td>
<td>2</td>
<td>3</td></tr>
<tr><td>4</td>
<td>5</td>
<td>6</td></tr></table>
<p>table th</p>
<table cellspacing="0" border="1"><tr><th>foo</th>
<th>bar</th>
<th>hoge</th></tr>
<tr><td>1</td>
<td>2</td>
<td>3</td></tr>
<tr><td>4</td>
<td>5</td>
<td>6</td></tr></table>
<p>table th2</p>
<table cellspacing="0" border="1"><tr><th>foo</th>
<td>bar</td>
<td>hoge</td></tr>
<tr><th>1</th>
<td>2</td>
<td>3</td></tr>
<tr><th>4</th>
<td>5</td>
<td>6</td></tr></table>
<p>table colspan</p>
<table cellspacing="0" border="1"><tr><th>foo</th>
<td colspan="2">bar</td>
<td>hoge</td></tr>
<tr><th>1</th>
<td>2</td>
<td>3</td>
<td>4</td></tr>
<tr><th>4</th>
<td>5</td>
<td colspan="2">6</td></tr></table>
<p>table rowspan</p>
<table cellspacing="0" border="1"><tr><th>foo</th>
<td rowspan="2">bar</td>
<td>hoge</td></tr>
<tr><th>1</th>
<td colspan="2">3</td></tr>
<tr><th>4</th>
<td>5</td>
<td>6</td></tr></table>
<p>箇条書</p>
<ul><li>挨拶
<ul><li>朝
<ul><li>おはよう
<li>ちぃーっす</ul>
<li>昼
<ul><li>こんにちは
<li>ちぃーっす</ul>
<li>夜
<ul><li>こんばんわ
<li>ちぃーっす</ul></ul>
<li>出発
<ul><li>出
<ul><li>いってきます
<li>ほな</ul>
<li>送
<ul><li>いってらっしゃい</ul></ul>
<li>帰宅
<ul><li>帰
<ul><li>ただいま
<li>ただいまもどりました</ul>
<li>迎
<ul><li>おかえり
<li>おかえりあそばせ</ul></ul></ul>
<p>表</p>
<table cellspacing="0" border="1"><tr><td rowspan="6">挨拶</td>
<td rowspan="2">朝</td>
<td>おはよう</td></tr>
<tr><td colspan="3">ちいーっす</td></tr>
<tr><td rowspan="2">昼</td>
<td colspan="2">こんにちは</td></tr>
<tr><td colspan="3">ちいーっす</td></tr>
<tr><td rowspan="2">夜</td>
<td colspan="2">こんばんわ</td></tr>
<tr><td colspan="3">ちいーっす</td></tr>
<tr><td rowspan="3">出発</td>
<td rowspan="2">出</td>
<td>いってきます</td></tr>
<tr><td colspan="3">ほな</td></tr>
<tr><td>送</td>
<td colspan="2">いってらっしゃい</td></tr>
<tr><td rowspan="4">帰宅</td>
<td rowspan="2">帰</td>
<td>ただいま</td></tr>
<tr><td colspan="3">ただいまもどりました</td></tr>
<tr><td rowspan="2">迎</td>
<td colspan="2">おかえり</td></tr>
<tr><td colspan="3">おかえりあそばせ</td></tr></table>
<p>tbl_ulモード</p>
<table cellspacing="0" border="1"><tr><td rowspan="6">挨拶</td>
<td rowspan="2">朝</td>
<td>おはよう</td></tr>
<tr><td colspan="3">ちぃーっす</td></tr>
<tr><td rowspan="2">昼</td>
<td colspan="2">こんにちは</td></tr>
<tr><td colspan="3">ちぃーっす</td></tr>
<tr><td rowspan="2">夜</td>
<td colspan="2">こんばんわ</td></tr>
<tr><td colspan="3">ちぃーっす</td></tr>
<tr><td rowspan="3">出発</td>
<td rowspan="2">出</td>
<td>いってきます</td></tr>
<tr><td colspan="3">ほな</td></tr>
<tr><td>送</td>
<td colspan="2">いってらっしゃい</td></tr>
<tr><td rowspan="4">帰宅</td>
<td rowspan="2">帰</td>
<td>ただいま</td></tr>
<tr><td colspan="3">ただいまもどりました</td></tr>
<tr><td rowspan="2">迎</td>
<td colspan="2">おかえり</td></tr>
<tr><td colspan="3">おかえりあそばせ</td></tr></table>
<p>tbl_orgとtbl_ulの結合</p>
<table cellspacing="0" border="1"><tr><th>種別</th>
<th>状況</th>
<th>セリフ</th></tr>
<tr><td rowspan="6">挨拶</td>
<td rowspan="2">朝</td>
<td>おはよう</td></tr>
<tr><td colspan="3">ちぃーっす</td></tr>
<tr><td rowspan="2">昼</td>
<td colspan="2">こんにちは</td></tr>
<tr><td colspan="3">ちぃーっす</td></tr>
<tr><td rowspan="2">夜</td>
<td colspan="2">こんばんわ</td></tr>
<tr><td colspan="3">ちぃーっす</td></tr>
<tr><td rowspan="3">出発</td>
<td rowspan="2">出</td>
<td>いってきます</td></tr>
<tr><td colspan="3">ほな</td></tr>
<tr><td>送</td>
<td colspan="2">いってらっしゃい</td></tr>
<tr><td rowspan="4">帰宅</td>
<td rowspan="2">帰</td>
<td>ただいま</td></tr>
<tr><td colspan="3">ただいまもどりました</td></tr>
<tr><td rowspan="2">迎</td>
<td colspan="2">おかえり</td></tr>
<tr><td colspan="3">おかえりあそばせ</td></tr></table>
<pre>ここはpre
</pre>
</body></html>
うまく動作して嬉しいので、他にも木構造を表にする例をば。
テキスト
肺 恒温 胎生 哺乳類 卵 鳥類 変温 卵 爬虫類 えら、肺 変温 卵 両生類 えら 変温 卵 魚類
箇条書
表
肺 | 恒温 | 胎生 | 哺乳類 |
卵 | 鳥類 | ||
変温 | 卵 | 爬虫類 | |
えら、肺 | 変温 | 卵 | 両生類 |
えら | 変温 | 卵 | 魚類 |
頭にヘッダの表を追加
tbl || 動物の分類の仕方 || 呼吸 | 体温 | 子の増やし方 | 分類 tbl_ul 肺 恒温 胎生 哺乳類 :
動物の分類の仕方 | |||
---|---|---|---|
呼吸 | 体温 | 子の増やし方 | 分類 |
肺 | 恒温 | 胎生 | 哺乳類 |
卵 | 鳥類 | ||
変温 | 卵 | 爬虫類 | |
えら、肺 | 変温 | 卵 | 両生類 |
えら | 変温 | 卵 | 魚類 |
簡単なテキストの表組みツール (C言語) や TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール) の表です。
今となっては思い出深いこの形式の表。
2000年代の中頃、某メーカーのガラケーの開発に関わっていた時に、 ワードで嫌という程書かされました。
シャープの桂さん、元気かな〜
(あ、言っちゃった)
関数名 | int foo_send(const unsigned char *buf, unsigned bytes) | |||
---|---|---|---|---|
説明 | データ送信開始 | |||
引数 | ||||
項番 | 仮引数名 | 型 | 説明 | |
1 | buf | const unsigned char * | 送信するデータの先頭アドレス | |
2 | bytes | unsigned | 送信するデータのバイト数(最大4096*9=36Kバイトまで指定可能) | |
返却値 | ||||
項番 | 型 | 説明 | ||
1 | int | 0 | FOO_OK | 正常終了 |
<0 | FOOO_EINVAL | パラメータの値が異常である | ||
FOO_EBUSY | 現在送信中である | |||
FOO_EIO | エラーが検出された | |||
FOO_ETIMEDOUT | タイムアウト発生 | |||
前提
FOOドライバが初期化されていること。すでに送信中でないこと。 結果 指定した長さのデータが、送信開始される。送信の完了はドライバ状態の通知を利用すること。 概略説明 指定されたデータを、DMA送信バッファにコピーして、送信を開始する。 |
ソースのテキストは
tbl ||関数名||int foo_send(const unsigned char *buf, unsigned bytes) ||説明 ||データ送信開始 |引数 ||項番 |仮引数名| 型 | 説明 |1 |buf |const unsigned char *|送信するデータの先頭アドレス |2 |bytes |unsigned |送信するデータのバイト数(最大4096*9=36Kバイトまで指定可能) |返却値 ||項番 |型 | 説明 tbl_ul 1 int 0 FOO_OK 正常終了 <0 FOOO_EINVAL パラメータの値が異常である FOO_EBUSY 現在送信中である FOO_EIO エラーが検出された FOO_ETIMEDOUT タイムアウト発生 前提\n\ FOOドライバが初期化されていること。すでに送信中でないこと。\n\ 結果\n\ 指定した長さのデータが、送信開始される。送信の完了はドライバ状態の通知を利用すること。\n\ 概略説明\n\ 指定されたデータを、DMA送信バッファにコピーして、送信を開始する。
冒頭で紹介した SMFの構造概略 の表で試してみましょう。
分類 | 種別 | データ長 | 内容 |
---|---|---|---|
ヘッダ | ID | 4バイト | "MThd" アスキー・コード 'M','T','h','d' の 4バイト |
サイズ | 4バイト | 以降のヘッダのバイト数をビッグエンディアンで格納
ヘッダの場合は値6固定なので、00,00,00,06 の4バイト | |
フォーマットタイプ | 2バイト | 値0, 1, 2 のいづれかをビッグエンディアンで格納
ここではフォーマットタイプ 0 の SMF のみ扱うので、 00,00 の2バイト | |
トラック数 | 2バイト | トラック数をビッグエンディアンで格納
フォーマットタイプが0の場合は、トラック数は1固定なので、 00,01 の2バイト | |
時間分解能 | 2バイト | 四分音符の分割数をビッグエンディアンで格納
四分音符1つをここで指定した値で分割した長さが、時間の最小単位 ただし1バイト目の最上位ビットが'1'の場合は、別の扱いとなる ここでは1バイト目の最上位ビットが'0'のSMFのみを扱う | |
トラック | ID | 4バイト | "MTrk" アスキー・コード 'M','T','r','k' の 4バイト |
サイズ | 4バイト | 以降のトラックのバイト数をビッグエンディアンで格納 | |
デルタタイム | 可変長 | - | |
イベント | 可変長 | - | |
デルタタイム | 可変長 | - | |
イベント | 可変長 | - | |
: | |||
デルタタイム | 可変長 | - | |
イベント | 可変長 | - |
ソースのテキストは
tbl ||分類|種別|データ長|内容 tbl_ul ヘッダ ID 4バイト "MThd" アスキー・コード 'M','T','h','d' の 4バイト サイズ 4バイト 以降のヘッダのバイト数をビッグエンディアンで格納\n\ ヘッダの場合は値6固定なので、00,00,00,06 の4バイト フォーマットタイプ 2バイト 値0, 1, 2 のいづれかをビッグエンディアンで格納\n\ ここではフォーマットタイプ 0 の SMF のみ扱うので、\n\ 00,00 の2バイト トラック数 2バイト トラック数をビッグエンディアンで格納\n\ フォーマットタイプが0の場合は、トラック数は1固定なので、\n\ 00,01 の2バイト 時間分解能 2バイト 四分音符の分割数をビッグエンディアンで格納\n\ 四分音符1つをここで指定した値で分割した長さが、時間の最小単位\n\ ただし1バイト目の最上位ビットが'1'の場合は、別の扱いとなる\n\ ここでは1バイト目の最上位ビットが'0'のSMFのみを扱う トラック ID 4バイト "MTrk" アスキー・コード 'M','T','r','k' の 4バイト サイズ 4バイト 以降のトラックのバイト数をビッグエンディアンで格納 デルタタイム 可変長 - イベント 可変長 - デルタタイム 可変長 - イベント 可変長 - : デルタタイム 可変長 - イベント 可変長 -
こうして試してみると、機能の不足が見えてきますね。
todo
この不具合をやっつけておきます。
まず現状の不具合を確認。
$ echo [[foo]] [[foo]] $ echo [[foo]] | ./ezmd.py - p: - a href="foo": foo $ echo '[[foo|bar]]' [[foo|bar]] $ echo '[[foo|bar]]' | ./ezmd.py - p: - a href="foo": bar $ echo '[[foo|bar|]]' | ./ezmd.py Traceback (most recent call last): : File "./ezmd.py", line 136, in <lambda> f = lambda i: cvs[i]( s3[i] ) File "./ezmd.py", line 132, in mcv (v1, v2) = lst_strip( s.split('|') ) if '|' in s else (s, s) ValueError: too many values to unpack $ echo '[[foo||bar]]' | ./ezmd.py Traceback (most recent call last): : File "./ezmd.py", line 136, in <lambda> f = lambda i: cvs[i]( s3[i] ) File "./ezmd.py", line 132, in mcv (v1, v2) = lst_strip( s.split('|') ) if '|' in s else (s, s) ValueError: too many values to unpack
文字列sに複数の'|'が含まれていると、 要素数3以上のlistが返って、(v1, v2)でunpackのエラー。
delim_pop()を追加して対応してみます。
def delim_pop(s, delim): f = lambda lst: ( lst[0], delim.join( lst[1:] ) ) return f( s.split(delim) )
v18.patch
diff -ur v17/ezmd.py v18/ezmd.py
--- v17/ezmd.py 2019-10-02 20:42:54.000000000 +0900
+++ v18/ezmd.py 2019-10-02 22:05:00.000000000 +0900
@@ -106,6 +106,10 @@
s_idx = lambda s, p, dv=-1: s.index(p) if p in s else dv
+def delim_pop(s, delim):
+ f = lambda lst: ( lst[0], delim.join( lst[1:] ) )
+ return f( s.split(delim) )
+
def do_v1v2(v1, v2):
if v1 == 'img':
return tag_new('img', {'src': v2}, '/')
@@ -129,8 +133,8 @@
s3 = lst_strip( ( s[:ih], s[ih+len(h):it], s[it+len(t):] ) )
def mcv(s):
- (v1, v2) = lst_strip( s.split('|') ) if '|' in s else (s, s)
- return do_v1v2(v1, v2)
+ (v1, v2) = lst_strip( delim_pop(s, '|') ) if '|' in s else (s, s)
+ return do_v1v2(v1, v2)
cvs = ( (lambda s: s), mcv, do_a_href )
f = lambda i: cvs[i]( s3[i] )
@@ -226,9 +230,7 @@
lst = parse_bar(s, 'td')
def split_num(s):
- s1 = s[1:]
- i = s_idx(s1, ' ')
- (t, s_) = ( s1[:i], s1[i+1:] ) if i >= 0 else (s, '')
+ (t, s_) = delim_pop( s[1:], ' ' )
return (t, s_) if t.isdigit() else ('', s)
def th_td(s, md):
$ cat v18.patch | patch -p1
改善の確認を。
$ echo [[foo]] | ./ezmd.py - p: - a href="foo": foo $ echo '[[foo|bar]]' | ./ezmd.py - p: - a href="foo": bar $ echo '[[foo|bar|]]' | ./ezmd.py - p: - a href="foo": bar| $ echo '[[foo||bar]]' | ./ezmd.py - p: - a href="foo": '|bar'
他に悪い影響出てないか確認を。
$ ./to_html.py head.yaml index.ez.txt ezmd | diff -u index.ez.html - $ $ ./to_html.py foo_head.yaml foo_17.txt | diff -u foo_17.html - $
OK
という事でページ冒頭の目次で、この章へのアンカーも無事に変換できてます。
todo
$ ./ezmd.py <<EOL > tbl > a|b|c > EOL - table cellspacing="0" border="1": - tr: - td: a - td: b - td: c $ ./ezmd.py <<EOL tbl a| |c EOL - table cellspacing="0" border="1": - tr: - td: a - td: '' - td: c
空欄のセルは作れますが、 ''になっているので、複数の空白とかは無理です。
def th_td(s, md): : return tag_new( md, prop, do_str( s.strip() ) )
この関数で最後に s.stipr() かけてます。
というか、そもそもセルの中で、先頭に複数の空白とか、ほぼ意味無いのでは?
$ ./ezhtml.py y <<EOL | tee foo_19_abc.html > - table cellspacing="0" border="1": > - tr: > - td: a > - td: ' b' > - td: c > EOL <table cellspacing="0" border="1"><tr><td>a</td> <td> b</td> <td>c</td></tr></table>
foo_19_abc.html
<table cellspacing="0" border="1"><tr><td>a</td>
<td> b</td>
<td>c</td></tr></table>
現状では、このようなHTMLデータが生成できない訳ですが...
実際にアンカーをクリックして「表」を表示してみても、 特に'b'の前にスペース空いてない様子ですね。
やはりあまり意味ないか。
元々こっちのモードの問題でした。
そもそも空欄のセルが作れない。
さかのぼると、ulモードでの箇条書で空欄の項目が作れない。
$ ./ezmd.py <<EOL > ul > a > > c > EOL - ul: - li /: a - li /: c $ ./ezmd.py <<EOL > ul > a > '' > c > EOL - ul: - li /: a - li /: '''''' - li /: c
だめ。
ソースコードでは
def do_mode_ul(buf, res): buf = esc_join(buf) buf = list( filter( lambda s: s.strip(), buf ) ) buf = list( map(idt_cnt, buf) ) # (i, s) :
ulモードの処理の冒頭で、 s.strip()かけて空文字になるような行は、除外してます。
- ul: - li /: a - li /: '' - li /: c
から
$ ./ezhtml.py y <<EOL | tee foo_19_ul.html > - ul: > - li /: a > - li /: '' > - li /: c > EOL <ul><li>a <li> <li>c</ul>
なHTMLデータを生成して
foo_19_ul.html
<ul><li>a
<li>
<li>c</ul>
これは意味あります。
そしてこのデータから、空欄セルを含む「表」にしたい。
行頭から字下げの空白の数が意味があって、 次に空欄を意味する何かが欲しい。
安易に'xxx'や"xxx"と、文字列全体を囲うパターンで考えてみると、
'や"で、最も外側で囲ってる場合は、それを「1回だけ」外す。
これにしてみますかな。
となると、これは
から使ってるdo_str()関数で対応。
# # sol : str or lst # def map_sol(f_s_ret_sol, sol): f = lambda o: o if isinstance(o, Empty) else f_s_ret_sol(o) return flat_map(f, sol) if type(sol) == list else f_s_ret_sol(sol) def do_str(sol): # str or list cvs = (do_br, do_a_href) for cv in cvs: sol = map_sol(cv, sol) return sol
ここで最初にdo_out_quoteという変換を追加してみます。
v19.patch
diff -ur v18/ezmd.py v19/ezmd.py
--- v18/ezmd.py 2019-10-02 22:05:00.000000000 +0900
+++ v19/ezmd.py 2019-10-02 23:31:00.000000000 +0900
@@ -141,6 +141,8 @@
return from_lst( cut_empty( flat_map( f, range(3) ) ) )
return s
+do_out_quote = lambda s: s [1:-1] if len(s) >= 2 and s[0] == s[-1] and s[0] in ("'", '"') else s
+
#
# sol : str or lst
#
@@ -149,7 +151,7 @@
return flat_map(f, sol) if type(sol) == list else f_s_ret_sol(sol)
def do_str(sol): # str or list
- cvs = (do_br, do_a_href)
+ cvs = (do_out_quote, do_br, do_a_href)
for cv in cvs:
sol = map_sol(cv, sol)
return sol
パッチを適用
$ cat v19.patch | patch -p1
何と言うか、これだけで目的の空欄のセルについては良さそうです。
動作確認。
$ ./ezmd.py <<EOL > ul > a > '' > c > EOL - ul: - li /: a - li /: '' - li /: c $ ./ezmd.py <<EOL > ul > a > I'm b > c > EOL - ul: - li /: a - li /: I'm b - li /: c $ ./ezmd.py <<EOL > ul > a > ' > c > EOL - ul: - li /: a - li /: '''' - li /: c
おや?
$ ( ./ezmd.py | ./ezhtml.py y ) <<EOL > ul > a > ' > c > EOL <ul><li>a <li>' <li>c</ul>
HTML形式は狙い通り。YAML形式の場合、そうなるのか...
tbl_ulの場合は
$ ./ezmd.py <<EOL > tbl > tbl_ul > a > '' > c > EOL - table cellspacing="0" border="1": - tr: - td colspan="2": a - tr: - td colspan="2": '' - tr: - td colspan="2": c $ ./ezmd.py <<EOL > tbl > tbl_ul > a > '' > c > '' > d > EOL - table cellspacing="0" border="1": - tr: - td: a - td: '' - td: c - tr: - td colspan="3": '' - tr: - td colspan="3": d
そして、「1回だけ」外す確認を
$ ./ezmd.py <<EOL > tbl > tbl_ul > a > '' > "'c'" > EOL - table cellspacing="0" border="1": - tr: - td: a - td: '' - td: '''c'''
おや?
$ ( ./ezmd.py | ./ezhtml.py y ) <<EOL > tbl > tbl_ul > a > '' > "'c'" > EOL <table cellspacing="0" border="1"><tr><td>a</td> <td></td> <td>'c'</td></tr></table>
やはりHTML形式にすると狙い通り。 (YAML形式のquoteは、少し直感的じゃないのかも)
SMFの構造概略 の場合
分類 | 種別 | データ長 | 内容 |
---|---|---|---|
ヘッダ | ID | 4バイト | "MThd" アスキー・コード 'M','T','h','d' の 4バイト |
サイズ | 4バイト | 以降のヘッダのバイト数をビッグエンディアンで格納
ヘッダの場合は値6固定なので、00,00,00,06 の4バイト | |
フォーマットタイプ | 2バイト | 値0, 1, 2 のいづれかをビッグエンディアンで格納
ここではフォーマットタイプ 0 の SMF のみ扱うので、 00,00 の2バイト | |
トラック数 | 2バイト | トラック数をビッグエンディアンで格納
フォーマットタイプが0の場合は、トラック数は1固定なので、 00,01 の2バイト | |
時間分解能 | 2バイト | 四分音符の分割数をビッグエンディアンで格納
四分音符1つをここで指定した値で分割した長さが、時間の最小単位 ただし1バイト目の最上位ビットが'1'の場合は、別の扱いとなる ここでは1バイト目の最上位ビットが'0'のSMFのみを扱う | |
トラック | ID | 4バイト | "MTrk" アスキー・コード 'M','T','r','k' の 4バイト |
サイズ | 4バイト | 以降のトラックのバイト数をビッグエンディアンで格納 | |
デルタタイム | 可変長 | ||
イベント | 可変長 | ||
デルタタイム | 可変長 | ||
イベント | 可変長 | ||
: | |||
デルタタイム | 可変長 | ||
イベント | 可変長 |
ソースのテキストは
tbl ||分類|種別|データ長|内容 tbl_ul ヘッダ ID 4バイト "MThd" アスキー・コード 'M','T','h','d' の 4バイト : イベント 可変長 '' : デルタタイム 可変長 '' イベント 可変長 ''
右下の空欄のセルが可能になりました。
で、「先頭に複数の空白」の要望は、 下から3行めの':'の前にスペースをとりたい所から来てます。
todo
tbl_orgモードでのthタグ、tdタグの切り替えは「||」だったので、その仕様に寄せておきます。
v20.patch
diff -ur v19/ezmd.py v20/ezmd.py
--- v19/ezmd.py 2019-10-02 23:31:00.000000000 +0900
+++ v20/ezmd.py 2019-10-03 22:27:36.000000000 +0900
@@ -286,6 +286,15 @@
(gw, gh) = sz_get(ul)
+ def li_to_name_v(o):
+ dv = ('td', o)
+ if not o or isinstance(o, Empty):
+ return dv
+ if type(o) == list:
+ (name, v) = li_to_name_v( o[0] )
+ return ( name, [v] + o[1:] )
+ return ( 'th', o[2:] ) if o.startswith('||') else dv
+
def cv_to_tbl(tag, x, tbl):
if tag.name == 'ul':
for tag_ in tag.v:
@@ -293,7 +302,8 @@
elif tag.name == 'li':
prop = {}
tr = tbl.v[-1]
- tr.v.append( tag_new('td', prop, tag.v) )
+ (name, v) = li_to_name_v(tag.v)
+ tr.v.append( tag_new(name, prop, v) )
(w, h) = sz_get(tag)
if h > 1:
$ cat v20.patch | patch -p1
実行してみます。
$ ./ezmd.py <<EOL > tbl > tbl_ul > foo > ||bar > hoge > |fuga > ||||th > ' ||td' > EOL - table border="1" cellspacing="0": - tr: - td: foo - th: bar - td: hoge - td: '|fuga' - tr: - th colspan="4": '||th' - tr: - td colspan="4": ' ||td'
大丈夫そうですね。
foo | bar | hoge | |fuga |
---|---|---|---|
||th | |||
||td |
では例によって
SMFの構造概略 の場合
分類 | 種別 | データ長 | 内容 |
---|---|---|---|
ヘッダ | ID | 4バイト | "MThd" アスキー・コード 'M','T','h','d' の 4バイト |
サイズ | 4バイト | 以降のヘッダのバイト数をビッグエンディアンで格納
ヘッダの場合は値6固定なので、00,00,00,06 の4バイト | |
フォーマットタイプ | 2バイト | 値0, 1, 2 のいづれかをビッグエンディアンで格納
ここではフォーマットタイプ 0 の SMF のみ扱うので、 00,00 の2バイト | |
トラック数 | 2バイト | トラック数をビッグエンディアンで格納
フォーマットタイプが0の場合は、トラック数は1固定なので、 00,01 の2バイト | |
時間分解能 | 2バイト | 四分音符の分割数をビッグエンディアンで格納
四分音符1つをここで指定した値で分割した長さが、時間の最小単位 ただし1バイト目の最上位ビットが'1'の場合は、別の扱いとなる ここでは1バイト目の最上位ビットが'0'のSMFのみを扱う | |
トラック | ID | 4バイト | "MTrk" アスキー・コード 'M','T','r','k' の 4バイト |
サイズ | 4バイト | 以降のトラックのバイト数をビッグエンディアンで格納 | |
デルタタイム | 可変長 | ||
イベント | 可変長 | ||
デルタタイム | 可変長 | ||
イベント | 可変長 | ||
: | |||
デルタタイム | 可変長 | ||
イベント | 可変長 |
ソースのテキストは
tbl tbl_ul ||分類 ||種別 ||データ長 ||内容 ||ヘッダ ID 4バイト "MThd" アスキー・コード 'M','T','h','d' の 4バイト : ||トラック ID 4バイト "MTrk" アスキー・コード 'M','T','r','k' の 4バイト '' : イベント 可変長 '' : デルタタイム 可変長 '' イベント 可変長 ''
tbl_orgモードなしで、tbl_ulモードだけでthタグ出来てます。
「ヘッダ」「トラック」もthタグに変更してみました。
todo
a (name)タグは、「バージョン8 目次機能」の中で、自動生成されて使われてます。
h1,h2,h3,...のタグを生成する箇所で
$ cat v8.patch : -def do_mode(mode, buf, res): +def do_mode(mode, buf, res, hd_names): if mode in heads: buf = lst_strip(buf) buf = list( filter( lambda s: s!='', buf ) ) s = ''.join(buf) - res.append( { mode: s } ) + (h_i, n) = ( int(mode[1:]), len(hd_names) ) + name = 'c_{}_{}'.format(h_i, n) + res.append( { mode: { 'a name="{}"'.format(name): s } } ) + hd_names.append( (h_i, n, name, s) ) + elif mode == 'p': buf = lst_strip(buf)
このように。
「バージョン15 タグ情報のデータ形式変更」 を経て、この箇所の現在は
def do_mode(mode, buf, res, hd_names): if mode in heads: buf = lst_strip(buf) buf = cut_empty(buf) s = ''.join(buf) (h_i, n) = ( int(mode[1:]), len(hd_names) ) name = 'c_{}_{}'.format(h_i, n) res.append( tag_new( mode, {}, tag_new('a', {'name': name}, s) ) ) hd_names.append( (h_i, n, name, s) )
このように。
実際に生成を試すと
$ ./ezmd.py <<EOL > h3 > foo > index > EOL - h3: a name="c_3_0": foo - ul: - li /: a href="#c_3_0": foo
この名前 "c_3_0" が自動な訳で、 別の箇所からここへのリンクを張ろうとしても、 生成してみないと判らない...
生成して判っても、さらに編集すると名前が変わるかもしれず、 結局は「使えない」状態...
現にこの章の冒頭で、 「バージョン8 目次機能」へのリンクを張りたかったのですが、 叶わなかった訳です。
ちゃんと明示的に
<a name="xxx"> yyy </a>
を埋めれるように対応してみます。
a (href)タグの場合は
テキスト [[v1|v2]] 内部データ ( 'a', {'href': v1}, v2 ) YAML { 'a href="v1"': v2 } HTML <a href="v1"> v2 </a>
でした。
から使ってるdo_str()関数の対応で、いけるかな?
ul,dlモード、「表」の中へとリンクを張るは、まぁないでしょう。 ほぼ、pモードのどこかへのリンクになるという事で。
また、目次のときの使い方のように、
<a href="v1"> v2 </a>
と、v2を抱え込む必要はないのかも知れません。
テキスト [[ name | xxx ]] 内部データ ( 'a', {'name: xxx}, '' ) YAML { 'a name="xxx": '' } HTML <a name="xxx"></a>
とりあえず、この仕様で。
v21.patch
diff -ur v20/ezmd.py v21/ezmd.py
--- v20/ezmd.py 2019-10-03 22:27:36.000000000 +0900
+++ v21/ezmd.py 2019-10-03 23:45:00.000000000 +0900
@@ -117,6 +117,8 @@
return tag_new('video', {'src': v2, 'controls': None, 'playsinline': None}, '')
if v1 == '-':
return tag_new('s', {}, v2)
+ if v1 == 'name':
+ return tag_new('a', {'name': v2}, '')
return tag_new('a', {'href': v1}, v2) if v1 else v2
def do_br(s):
これだけで済みました。
$ cat v21.patch | patch -p1
試してみます。
$ ./ezmd.py <<EOL > foo [[name|bar]] hoge > > [[#bar|fuga]] > EOL - p: - foo - a name="bar": '' - hoge - p: - a href="#bar": fuga $ ./ezmd.py <<EOL | ./ezhtml.py y > foo [[name|bar]] hoge > > [[#bar|fuga]] > EOL <p>foo <a name="bar"></a> hoge</p> <p><a href="#bar">fuga</a></p>
このような感じです。
これで晴れて バージョン8 目次機能 や バージョン15 タグ情報のデータ形式変更 へとリンクが張れました。
todo
todoの 「tblのセルの中の文字列で、先頭に複数の空白を含めたい」 と関連するか微妙ですが、 ちょいと大きな変更を。
以前に少し、 「表」のtableタグが「入れ子」の構造を可能にしていた事からか、 「ページのレイアウトを整えるため」などと、 本来と違う目的のためにtableタグが乱用された時代があった事を言及しました。
かく言う自分もその昔、
お仕事で組み込み用の小さなブラウザなどを開発してた時に、
tableタグの「入れ子」を使って、
疑似フレーム対応してたような気がします。
(式神ブラウザ「ヘクトアイ」などと申しておりまして...)
表のセルの中に、h1,h2,h3タグでヘッダをうって、pタグで段落つけて、preタグの内容を、 などと記述したくはありませんが...
表のセルの中に、ulやdlのリストを入れるくらいは、やりたいかも。
それ使うかどうかは別として、そう出来るように作っておいてもいいのかも。
現状では、トップレベルでモードを遷移させつつタグ生成しています。 なので、tblモード中のセルの処理の中で、ulモードに移ることは叶いません。
直接入れ子の記述は出来ませんが、次のような策でいきます。
リストの切替え指示はどうするか?
swbufモードを追加します。
'swbuf'だけの行が現れるとswbufモードに。
そこから他のモードになるまでの区間で、 切替える先のバッファ名を指定します。
swbuf バッファ名
バッファ名の指定が無ければ、 元のデフォルトの出力先に戻します。
sbuf
「貼り付け」の指示は、例によって「あの形式」で指定します。
[[ paste | バッファ名 ]]
で、処理中のデータに、バッファ名のバッファに溜っている内容を貼り付けます。
使い方を誤ると、「何とでも破綻し得る」危険な仕様です。
v22.patch
diff -ur v21/ezmd.py v22/ezmd.py
--- v21/ezmd.py 2019-10-03 23:45:00.000000000 +0900
+++ v22/ezmd.py 2019-10-04 20:10:13.000000000 +0900
@@ -5,7 +5,7 @@
import nkf
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
-modes = heads + [ 'p', 'pre', 'ul', 'dl', 'tbl', 'index' ]
+modes = heads + [ 'p', 'pre', 'ul', 'dl', 'tbl', 'index', 'swbuf' ]
is_all_ge_n = lambda s, c, n: all( map( lambda c_: c_ == c, s ) ) and len(s) >= n
@@ -35,6 +35,43 @@
setattr(self, k, v)
return self
+def outbuf_new():
+ d = {}
+ e = Empty()
+
+ def swbuf(name=''):
+ if not name:
+ name = 'org'
+ if name not in d:
+ d[ name ] = []
+ e.name = name
+
+ lst_get = lambda name='': d.get( name if name else e.name, [] )
+ append = lambda o: lst_get().append(o)
+ extend = lambda o: lst_get().extend(o)
+
+ stk = []
+ def tmp_name():
+ nm_i = lambda i: 'tmp_' + str(i)
+ i = 0
+ while nm_i(i) in d:
+ i += 1
+ return nm_i(i)
+ def push_tmp():
+ stk.append( e.name )
+ swbuf( tmp_name() )
+ def pop_tmp():
+ if not e.name.startswith('tmp_') or not stk:
+ return []
+ lst = d.pop(e.name)
+ swbuf( stk.pop() )
+ return lst
+
+ swbuf()
+ return e.to_attr( locals() )
+
+outbuf = outbuf_new()
+
def tag_new(name, prop, v):
return Empty( locals() )
@@ -119,6 +156,8 @@
return tag_new('s', {}, v2)
if v1 == 'name':
return tag_new('a', {'name': v2}, '')
+ if v1 == 'paste':
+ return outbuf.lst_get(v2)
return tag_new('a', {'href': v1}, v2) if v1 else v2
def do_br(s):
@@ -158,7 +197,7 @@
sol = map_sol(cv, sol)
return sol
-def do_mode_ul(buf, res):
+def do_mode_ul(buf):
buf = esc_join(buf)
buf = list( filter( lambda s: s.strip(), buf ) )
buf = list( map(idt_cnt, buf) ) # (i, s)
@@ -191,9 +230,9 @@
lst = list( map(f, lst) )
return tag_new('ul', {}, lst)
- res.extend( list( map(lst_to, lsts) ) )
+ outbuf.extend( list( map(lst_to, lsts) ) )
-def do_mode_dl(buf, res):
+def do_mode_dl(buf):
buf = lst_to_empty(buf)
buf = cut_ht_empty(buf)
if buf:
@@ -212,7 +251,7 @@
e = buf_loop_new(buf, is_call, func)
e.run()
- res.append( tag_new('dl', {}, lst) )
+ outbuf.append( tag_new('dl', {}, lst) )
def do_tr(s):
tgl = lambda md, n: md if n == 1 else ('th' if md == 'td' else 'td')
@@ -254,13 +293,13 @@
tbl_prop = { 'border': 1, 'cellspacing': 0 }
-def do_tbl_org(buf, res):
+def do_tbl_org(buf):
buf = esc_join(buf)
buf = lst_strip(buf)
buf = cut_empty(buf)
if buf:
v = list( map(do_tr, buf) )
- res.append( tag_new('table', tbl_prop, v) )
+ outbuf.append( tag_new('table', tbl_prop, v) )
def ul_to_tbl(ul):
def pack_ul(ul):
@@ -329,11 +368,12 @@
trs.pop()
return tbl
-def do_tbl_ul(buf, res):
- uls = []
- do_mode_ul(buf, uls)
+def do_tbl_ul(buf):
+ outbuf.push_tmp()
+ do_mode_ul(buf)
+ uls = outbuf.pop_tmp()
for ul in uls:
- res.append( ul_to_tbl(ul) )
+ outbuf.append( ul_to_tbl(ul) )
def tbls_join(tbls):
def w_get(tag):
@@ -361,8 +401,8 @@
prop = tbls[0].prop
return tag_new('table', prop, trs)
-def do_mode_tbl(buf, res):
- res_ = []
+def do_mode_tbl(buf):
+ outbuf.push_tmp()
def is_call(e):
if e.s in ('tbl_org', 'tbl_ul'):
@@ -373,24 +413,24 @@
def func(e):
if e.mode == 'tbl_org':
- do_tbl_org(e.tmp, res_)
+ do_tbl_org(e.tmp)
elif e.mode == 'tbl_ul':
- do_tbl_ul(e.tmp, res_)
+ do_tbl_ul(e.tmp)
e = buf_loop_new(buf, is_call, func)
e.mode = 'tbl_org'
e.run()
- res.append( tbls_join(res_) )
+ outbuf.append( tbls_join( outbuf.pop_tmp() ) )
-def do_mode(mode, buf, res, hd_names):
+def do_mode(mode, buf, hd_names):
if mode in heads:
buf = lst_strip(buf)
buf = cut_empty(buf)
s = ''.join(buf)
(h_i, n) = ( int(mode[1:]), len(hd_names) )
name = 'c_{}_{}'.format(h_i, n)
- res.append( tag_new( mode, {}, tag_new('a', {'name': name}, s) ) )
+ outbuf.append( tag_new( mode, {}, tag_new('a', {'name': name}, s) ) )
hd_names.append( (h_i, n, name, s) )
elif mode == 'p':
@@ -406,27 +446,33 @@
lst = []
for lst in lsts:
lst = flat_map(do_str, lst)
- res.append( tag_new('p', {}, lst) )
+ if lst:
+ outbuf.append( tag_new('p', {}, lst) )
elif mode == 'pre':
buf = cut_ht_empty(buf)
if buf:
buf = cut_verb_idt(buf)
s = '\n'.join(buf) + '\n'
- res.append( tag_new('pre', {}, s) )
+ outbuf.append( tag_new('pre', {}, s) )
elif mode == 'ul':
- do_mode_ul(buf, res)
+ do_mode_ul(buf)
elif mode == 'dl':
- do_mode_dl(buf, res)
+ do_mode_dl(buf)
elif mode == 'tbl':
- do_mode_tbl(buf, res)
+ do_mode_tbl(buf)
elif mode == 'hr':
- res.extend( [ tag_new('p', {}, tag_new('hr', {}, '/') ) ] * len(buf) )
+ outbuf.extend( [ tag_new('p', {}, tag_new('hr', {}, '/') ) ] * len(buf) )
elif mode == 'index':
buf = lst_strip(buf)
buf = cut_empty(buf)
- res.append( tag_new('index', {}, buf) ) # continue to 2 pass
+ outbuf.append( tag_new('index', {}, buf) ) # continue to 2 pass
+ elif mode == 'swbuf':
+ buf = lst_strip(buf)
+ buf = cut_empty(buf)
+ name = buf[0] if buf else ''
+ outbuf.swbuf(name)
-def do_index(lst, hd_names):
+def do_index(hd_names):
def slice_get(buf):
slc = ':'
@@ -453,26 +499,26 @@
func = lambda h_i, n, name, s: ' ' * h_i + '[[#{}|'.format(name) + s + ']]'
buf = list( map( lambda vs: func(*vs), names ) )
- ul_res = []
- do_mode_ul(buf, ul_res)
- return ul_res
+ outbuf.push_tmp()
+ do_mode_ul(buf)
+ return outbuf.pop_tmp()
- return flat_map( lambda tag: f(tag.v) if tag.name == 'index' else tag, lst )
+ return flat_map( lambda tag: f(tag.v) if tag.name == 'index' else tag, outbuf.lst_get() )
def ezmd(lst):
lst = ['p'] + lst
- (buf, res, hd_names) = ( [], [], [] )
+ (buf, hd_names) = ( [], [] )
def is_call(e):
(e.s, e.next_mode) = next_mode_switch(e.s, e.mode)
return e.next_mode != e.mode
- func = lambda e: do_mode(e.mode, e.tmp, res, hd_names)
+ func = lambda e: do_mode(e.mode, e.tmp, hd_names)
e = buf_loop_new(lst, is_call, func)
e.run()
- res = do_index(res, hd_names)
+ res = do_index(hd_names)
return res
def yaml_dump(o):
$ cat v22.patch | patch -p1
試してみます。
$ ./ezmd.py <<EOL > swbuf > foo > p > FOO > swbuf > p > bar [[paste|foo]] hoge > > [[paste|foo]] > EOL - p: - bar - p: - FOO - hoge - p: - p: - FOO
pタグの「入れ子」になってますが、一応意図した通りです。
色々試してみます。
p foo swbuf buf_ul ul bar hoge swbuf buf_dl dl bar hoge swbuf p bar tbl foo | [[ paste \| buf_ul ]] [[ paste \| buf_dl ]] p hello tbl tbl_ul foo [[ paste | buf_dl ]] [[ paste | buf_ul ]] p paste buf_ul [[ paste | buf_ul ]] paste buf_dl [[ paste | buf_dl ]] paste buf_dl in ul ul abc [[ paste | buf_dl ]] p paste buf_ul in dl dl abc [[ paste | buf_ul ]]
結果は
foo
bar
foo |
|
|
hello
foo |
|
|
paste buf_ul
paste buf_dl
paste buf_dl in ul
paste buf_ul in dl
表のセルの中にリストを入れると、 下部にスペースが空いてしまうようです。
その他は意図した通りです。
表のセルの中にpreタグも入るだろうか?
swbuf buf_aa pre int 123 double 123.445 / swbuf buf_bb dl int 123 double 123.456 swbuf tbl tbl_ul pre [[paste|buf_aa]] dl [[paste|buf_bb]]
pre | int 123 double 123.445 |
dl |
|
OK 入りました。
では
簡単なテキストの表組みツール (C言語)
や
TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール)
の表です。
関数名 | int foo_send(const unsigned char *buf, unsigned bytes) | |||
---|---|---|---|---|
説明 | データ送信開始 | |||
引数 | ||||
項番 | 仮引数名 | 型 | 説明 | |
1 | buf | const unsigned char * | 送信するデータの先頭アドレス | |
2 | bytes | unsigned | 送信するデータのバイト数(最大4096*9=36Kバイトまで指定可能) | |
返却値 | ||||
項番 | 型 | 説明 | ||
1 | int | 0 | FOO_OK | 正常終了 |
<0 | FOOO_EINVAL | パラメータの値が異常である | ||
FOO_EBUSY | 現在送信中である | |||
FOO_EIO | エラーが検出された | |||
FOO_ETIMEDOUT | タイムアウト発生 | |||
|
末尾のセルの中で、dlタグを使ったバッファから貼ってます。
トップページ からの 更新履歴 も、 更新履歴用のテキスト から生成するようにしてみました。
todo
ちょっとでも楽をしようと。
例えば自分でテキストを書いてみると
h2 見出しA p 段落A pre : / 段落B :
なパターンがとても多く。
h1,h2,h3,... で見出しの内容のあと空行があると、 デフォルトpモードに遷移する事にします。
h2 見出しA 段落A pre : / 段落B :
や
h2 見出 し A 段落A pre : / 段落B :
などが可能になります。
v23.patch
diff -ur v22/ezmd.py v23/ezmd.py
--- v22/ezmd.py 2019-10-04 20:10:13.000000000 +0900
+++ v23/ezmd.py 2019-10-06 13:12:35.000000000 +0900
@@ -9,22 +9,19 @@
is_all_ge_n = lambda s, c, n: all( map( lambda c_: c_ == c, s ) ) and len(s) >= n
-def next_mode_switch(s, mode):
- if mode == 'pre':
- return (None, 'p') if s == '/' else (s, mode)
-
- if s in modes:
- return (None, s) if s != mode else (None, mode)
-
- if is_all_ge_n(s, '-', 4):
- return (s, 'hr')
-
- if mode == 'hr':
- if is_all_ge_n(s, '-', 4):
- return (s, 'hr')
- return (s, 'p')
-
- return (s, mode)
+def next_mode_switch(e):
+ if (e.mode, e.s) == ('pre', '/'):
+ (e.s, e.next_mode) = (None, 'p')
+ elif e.mode in heads and not e.s.strip():
+ (e.s, e.next_mode) = (None, 'p' if e.tmp else e.mode)
+ elif e.s in modes:
+ (e.s, e.next_mode) = (None, e.s)
+ elif is_all_ge_n(e.s, '-', 4):
+ e.next_mode = 'hr'
+ elif e.mode == 'hr':
+ e.next_mode = 'hr' if is_all_ge_n(e.s, '-', 4) else 'p'
+ else:
+ e.next_mode = e.mode
class Empty:
def __init__(self, dic={}):
@@ -510,7 +507,7 @@
(buf, hd_names) = ( [], [] )
def is_call(e):
- (e.s, e.next_mode) = next_mode_switch(e.s, e.mode)
+ next_mode_switch(e)
return e.next_mode != e.mode
func = lambda e: do_mode(e.mode, e.tmp, hd_names)
$ cat v23.patch | patch -p1
まずはいつもの動作確認を。
$ ./to_html.py head.yaml index.ez.txt ezmd | diff -u index.ez.html - $
OK
$ ./ezmd.py <<EOL > h1 > > foo > bar > > p > hoge > EOL - h1: a name="c_1_0": foobar - p: - hoge
に対して
$ ./ezmd.py <<EOL > h1 > > foo > bar > > hoge > EOL - h1: a name="c_1_0": foobar - p: - hoge
OK
$ ./ezmd.py <<EOL > h1 > foobar > p > hoge > EOL - h1: a name="c_1_0": foobar - p: - hoge
に対しても
$ ./ezmd.py <<EOL > h1 > foobar > > hoge > EOL - h1: a name="c_1_0": foobar - p: - hoge
OK
index.ez.txt から、h1,h2,h3指定の後の省略できる'p'行を削除して確認してみます。
$ cp index.ez.txt index.ezz.txt
index.ezz.txt編集
$ diff -u index.ez.txt index.ezz.txt | nkf -u --- index.ez.txt 2019-09-27 22:37:18.000000000 +0900 +++ index.ezz.txt 2019-10-06 13:36:18.000000000 +0900 @@ -9,7 +9,6 @@ h2 はじめに -p 以前に [[ http://kondoh.html.xdomain.jp/ezhtml/index.html | 簡易なHTMLパーサ 2018秋 ]] を作成しました。 @@ -150,7 +149,6 @@ h2 headとbody -p [[ foo.yaml ]] の段階で、headとbodyに分かれてます。 @@ -263,7 +261,6 @@ h2 タグ -p おれおれ仕様のツールなので、 自分がよく使うHTMLのタグだけ対応して、 滅多に使わないものは、最後に手動で編集する事にします。 @@ -300,7 +297,6 @@ h2 簡易にモード切り替えで -p [[ foo.txt ]] から [[ foo_body.yaml ]] @@ -398,7 +394,6 @@ h3 h1, h2, h3モード -p 他のモードに切り替わるまでの間の複数行のテキストについて ul @@ -425,7 +420,6 @@ h3 pモード -p 他のモードに切り替わるまでの間の複数行のテキストについて ul @@ -472,7 +466,6 @@ h2 バージョン1 (h,pタグ) -p ではこの仕様で、骨組みのコーディング。 [[ ezmd.py ]] @@ -706,7 +699,6 @@ h3 preモード -p preタグの場合、どこまでがpreタグの中か? 次のモードへの切り替えの判定が微妙です。 @@ -918,7 +910,6 @@ h3 ulモード -p 全体の簡単にするためにモードの開始、終了をトップレベルの状態の遷移だけにしました。 なので、基本的に「入れ子」の構造を諦めてます。 @@ -1583,7 +1574,6 @@ h2 バージョン8 目次機能 -p 目次を自動生成する機能を追加してみます。 さすがにこの機能は2 passになります。 @@ -1846,7 +1836,6 @@ h2 バージョン9 headタグのtitleを何とかする -p 自分ではいつもheadタグには日本語は書かないので、 ここは安易に @@ -1898,7 +1887,6 @@ h3 まずは不具合の修正 -p 色々試してみて不具合でました。 ulタグの処理前に、字下げの絡みで行の結合をする箇所。 @@ -1928,7 +1916,6 @@ h3 調整 -p 次の調整を入れておきます。 ul @@ -1946,7 +1933,6 @@ h3 お試し -p では満を持して、このページ自身もこの仕様のテキストで書いてみましょう。 [[ head.yaml ]]
削除した'p'行は
$ wc -l index.ez.txt 1983 index.ez.txt $ wc -l index.ezz.txt 1969 index.ezz.txt $ expr 1983 - 1969 14
14行
$ ./to_html.py head.yaml index.ezz.txt ezmd | diff -u index.ez.html - $
OK
todo
このページの バージョン14 (table) の表示が乱れていました。
先の v23.patch の next_mode_switch()関数の変更にバグがありました。
例えば
$ ./ezmd.py <<EOL > pre > tbl > foo|bar > / > EOL - table border="1" cellspacing="0": - tr: - td: foo - td: bar - tr: - td colspan="2": /
preモードからは'/'行でしかモード遷移しないはずが、 tblモードに移ってしまってます。
修正しておきます。
v24.patch
diff -ur v23/ezmd.py v24/ezmd.py
--- v23/ezmd.py 2019-10-06 13:12:35.000000000 +0900
+++ v24/ezmd.py 2019-10-07 04:19:38.000000000 +0900
@@ -10,8 +10,10 @@
is_all_ge_n = lambda s, c, n: all( map( lambda c_: c_ == c, s ) ) and len(s) >= n
def next_mode_switch(e):
- if (e.mode, e.s) == ('pre', '/'):
- (e.s, e.next_mode) = (None, 'p')
+ e.next_mode = e.mode
+ if e.mode == 'pre':
+ if e.s == '/':
+ (e.s, e.next_mode) = (None, 'p')
elif e.mode in heads and not e.s.strip():
(e.s, e.next_mode) = (None, 'p' if e.tmp else e.mode)
elif e.s in modes:
@@ -20,8 +22,6 @@
e.next_mode = 'hr'
elif e.mode == 'hr':
e.next_mode = 'hr' if is_all_ge_n(e.s, '-', 4) else 'p'
- else:
- e.next_mode = e.mode
class Empty:
def __init__(self, dic={}):
$ cat v24.patch | patch -p1
確認を。
$ ./ezmd.py <<EOL > pre > tbl > foo|bar > / > EOL - pre: | tbl foo|bar
OK
そして、いつもの確認も。
$ ./to_html.py head.yaml index.ez.txt ezmd | diff -u index.ez.html - $ $ ./to_html.py head.yaml index.ezz.txt ezmd | diff -u index.ez.html - $
OK
todo
todo
そのものの対応ではないのですが、 表のサンプルを意図した表示に近づけるべく、 手を入れてみました。
プロパティは面倒なので、 自分ではあまり指定したくありませんが...
細かく指定可能なように作っておくのは、それはそれで必要かと。
モードの切替え時にプロパティを指定する案もありますが、
例えばtblモードの中では、tr, th, td が多数、入り乱れて生成されるので、 狙ったタグにプロパティの指定を追加するのは困難です。
困った時の
頼み。(長い)
tag_props という辞書を追加して ここに「現在の」プロパティの辞書を、タグ名ごとに登録します。
do_str()からの登録は例の形式
[[ prop | { YAML形式のプロパティの辞書 } ]]
でtag_props全体に上書きで登録します。
[[ prop | {} ]] [[ prop ]]
ならtag_propsクリア。
tag_new()関数から、tag_propsを参照。 作成するタグ名のプロパティが見つかれば、 そのプロパティ辞書をベースにして、 引数のプロパティを追加、上書きして使用します。
tblモードのローカル・モードtbl_ulでは、 一旦liタグを含むulタグを生成してから、 まとめてtable, tr, th, tdタグに変換します。
tblモードでプロパティの指定をしたかったのですが、 この仕様を素直に使ってる限り、 ul, liタグの段階までしかプロパティが指定できません。
liタグがth, tdタグへと変換されるので、 liタグの段階で、th, tdタグに指定したいプロパティを指定するという、 強引な解決にしておきます。
さらにややこしい事に、 変換処理中にliタグには、 内部的に'sub_ul'というプロパティを追加して使っていました。
liタグからth, tdタグに変換する際には、 この'sub_ul'以外のプロパティだけを、引き継がせるようにしました。
また、liタグはデフォルトで終了タグなしにするため、 内部的に'/'というプロパティを持たせてます。
これをそのままth, tdタグが引き継ぐと、終了タグが消えてしまいます。
ilタグからプロパティ'/'は、引き継がないように。
(ああ、ややこしい)
指定行は、奥深くで状態を変更するだけで、 それ自体は何も表示する物を生成しません。
li, tr, th, tdタグを生成する箇所で、 空リスト[]を値にしたタグを生成するケースが出てしまい、 意図しない不要な空行などが表示されたりしました。
map()関数の処理を、手製のflat_map()関数に置き換えて、 リスト要素の空リストを消すように、 場当たり的に対処してみました。
ここまでは、自分でよく使う「打ち消し線」だけ対応してました。
[[ - | xxx ]]
で
YAML形式 { s: xxx }
で
HTML形式 <s> xxx </s>
についても同じような「手間」なので、 まとめて対応を入れておきます。
打ち消し線 [[ s | xxx ]] [[ - | xxx ]] 強調(イタリック?) [[ em | xxx ]] [[ * | xxx ]] 強い強調(太字?) [[ strong | xxx ]] [[ ** | xxx ]] 下線(アンダーライン) [[ u | xxx ]] [[ _ | xxx ]] 斜体(イタリック) [[ i | xxx ]] [[ / | xxx ]] 太字(ボールド) [[ b | xxx ]]
v25.patch
diff -ur v24/ezmd.py v25/ezmd.py
--- v24/ezmd.py 2019-10-07 04:19:38.000000000 +0900
+++ v25/ezmd.py 2019-10-07 22:18:22.000000000 +0900
@@ -69,7 +69,14 @@
outbuf = outbuf_new()
+tag_props = {}
+
def tag_new(name, prop, v):
+ b = tag_props.get(name, {})
+ if b:
+ (arg, prop) = ( prop, b.copy() )
+ prop.update(arg)
+
return Empty( locals() )
def tag_to_dic(tag):
@@ -144,17 +151,36 @@
f = lambda lst: ( lst[0], delim.join( lst[1:] ) )
return f( s.split(delim) )
+def do_prop(v1, v2):
+ tag_props.clear()
+ if v2 and v2 != v1:
+ try:
+ d = yaml.load(v2)
+ if type(d) == dict:
+ tag_props.update(d)
+ except:
+ pass
+ return []
+
def do_v1v2(v1, v2):
+ lst = ('s', 'em', 'strong', 'u', 'i', 'b')
+ if v1 in lst:
+ return tag_new(v1, {}, v2)
+
+ d = { '-': 's', '*': 'em', '**': 'strong', '_': 'u', '/': 'i' }
+ if v1 in d:
+ return tag_new( d.get(v1), {}, v2 )
+
if v1 == 'img':
return tag_new('img', {'src': v2}, '/')
if v1 == 'video':
return tag_new('video', {'src': v2, 'controls': None, 'playsinline': None}, '')
- if v1 == '-':
- return tag_new('s', {}, v2)
if v1 == 'name':
return tag_new('a', {'name': v2}, '')
if v1 == 'paste':
return outbuf.lst_get(v2)
+ if v1 == 'prop':
+ return do_prop(v1, v2)
return tag_new('a', {'href': v1}, v2) if v1 else v2
def do_br(s):
@@ -223,8 +249,11 @@
list( map(buf_to_stk_lsts, buf) ) # make lists
def lst_to(lst):
- f = lambda o: lst_to(o) if type(o) == list else tag_new( 'li', {'/': None}, do_str(o) )
- lst = list( map(f, lst) )
+ def fs(s):
+ sol = do_str(s)
+ return tag_new( 'li', {'/': None}, sol ) if sol != [] else []
+ f = lambda o: lst_to(o) if type(o) == list else fs(o)
+ lst = list( flat_map(f, lst) )
return tag_new('ul', {}, lst)
outbuf.extend( list( map(lst_to, lsts) ) )
@@ -283,10 +312,11 @@
(t, s) = split_num(s)
if t:
prop[ '{}span'.format(cr) ] = int(t)
- return tag_new( md, prop, do_str( s.strip() ) )
+ v = do_str( s.strip() )
+ return tag_new(md, prop, v) if v != [] else []
lst = flat_map( lambda s_md: th_td(*s_md), lst )
- return tag_new('tr', {}, lst)
+ return tag_new('tr', {}, lst) if lst != [] else []
tbl_prop = { 'border': 1, 'cellspacing': 0 }
@@ -295,7 +325,7 @@
buf = lst_strip(buf)
buf = cut_empty(buf)
if buf:
- v = list( map(do_tr, buf) )
+ v = list( flat_map(do_tr, buf) )
outbuf.append( tag_new('table', tbl_prop, v) )
def ul_to_tbl(ul):
@@ -339,6 +369,7 @@
cv_to_tbl(tag_, x, tbl)
elif tag.name == 'li':
prop = {}
+ prop.update( dict( filter( lambda kv: kv[0] not in ('sub_ul', '/'), tag.prop.items() ) ) )
tr = tbl.v[-1]
(name, v) = li_to_name_v(tag.v)
tr.v.append( tag_new(name, prop, v) )
$ cat v25.patch | patch -p1
$ ./to_html.py head.yaml index.ezz.txt ezmd | diff -u index.ez.html - $ $ rm -rf ttt ; mkdir ttt ; cd ttt $ wget http://kondoh.html.xdomain.jp/ezmd/index.txt $ wget http://kondoh.html.xdomain.jp/ezmd/index.html $ mv index.txt ../index-v24.txt $ mv index.html ../index-v24.html $ cd .. ; rm -rf ttt $ ./to_html.py head.yaml index-v24.txt ezmd | diff -u index-v24.html - $
OK
abcdefghijklmnopqrstuvwxyz | ||
foo | bar | hoge |
foo | bar | hoge |
foo | ||
bar | ||
hoge | ||
foo | ||
bar | ||
hoge |
[[s|打ち消し]] [[-|打ち消し]] [[em|強調]] [[*|強調]] [[strong|強い強調]] [[**|強い強調]] [[u|下線]] [[_|下線]] [[i|斜体]] [[/|斜体]] [[b|太字]]
打ち消し
打ち消し
強調
強調
強い強調
強い強調
下線
下線
斜体
斜体
太字
強調 |
強調 |
強い強調 |
強い強調 |
下線 |
下線 |
斜体 |
斜体 |
太字 |
$ ./to_html.py head.yaml ex_tbl.txt ex_tbl > ex_tbl.html
ex_tbl.html
<html><head>
<head>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-137368912-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-137368912-1');
</script>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>ex_tbl</title>
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head>
</head><body>
<h1><a name="c_1_0">表のサンプル</a></h1>
<h3><a name="c_3_1">midiのときの表</a></h3>
<p><a href="http://kondoh.html.xdomain.jp/midi.html#smf_outline">SMFの構造概略</a></p>
<table cellspacing="0" border="1"><tr><th>分類</th>
<th>種別</th>
<th>データ長</th>
<th>内容</th></tr>
<tr><th rowspan="5">ヘッダ</th>
<td>ID</td>
<td>4バイト</td>
<td>"MThd" アスキー・コード 'M','T','h','d' の 4バイト</td></tr>
<tr><td>サイズ</td>
<td>4バイト</td>
<td colspan="2">以降のヘッダのバイト数をビッグエンディアンで格納
<br>
ヘッダの場合は値6固定なので、00,00,00,06 の4バイト</td></tr>
<tr><td>フォーマットタイプ</td>
<td>2バイト</td>
<td colspan="2">値0, 1, 2 のいづれかをビッグエンディアンで格納
<br>
ここではフォーマットタイプ 0 の SMF のみ扱うので、
<br>
00,00 の2バイト</td></tr>
<tr><td>トラック数</td>
<td>2バイト</td>
<td colspan="2">トラック数をビッグエンディアンで格納
<br>
フォーマットタイプが0の場合は、トラック数は1固定なので、
<br>
00,01 の2バイト</td></tr>
<tr><td>時間分解能</td>
<td>2バイト</td>
<td colspan="2">四分音符の分割数をビッグエンディアンで格納
<br>
四分音符1つをここで指定した値で分割した長さが、時間の最小単位
<br>
ただし1バイト目の最上位ビットが'1'の場合は、別の扱いとなる
<br>
ここでは1バイト目の最上位ビットが'0'のSMFのみを扱う</td></tr>
<tr><th rowspan="9">トラック</th>
<td>ID</td>
<td>4バイト</td>
<td>"MTrk" アスキー・コード 'M','T','r','k' の 4バイト</td></tr>
<tr><td>サイズ</td>
<td>4バイト</td>
<td colspan="2">以降のトラックのバイト数をビッグエンディアンで格納</td></tr>
<tr><td>デルタタイム</td>
<td>可変長</td>
<td colspan="2"></td></tr>
<tr><td>イベント</td>
<td>可変長</td>
<td colspan="2"></td></tr>
<tr><td>デルタタイム</td>
<td>可変長</td>
<td colspan="2"></td></tr>
<tr><td>イベント</td>
<td>可変長</td>
<td colspan="2"></td></tr>
<tr><td colspan="4" align="center">:</td></tr>
<tr><td>デルタタイム</td>
<td>可変長</td>
<td colspan="2"></td></tr>
<tr><td>イベント</td>
<td>可変長</td>
<td colspan="2"></td></tr></table>
<p><hr></p>
<h3><a name="c_3_2">TXTBLのときの例の表</a></h3>
<p><a href="http://kondoh.html.xdomain.jp/txtbl.html">簡単なテキストの表組みツール (C言語)</a>
<br>
<a href="http://kondoh.html.xdomain.jp/txtblcnt.html">TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール)</a></p>
<table cellspacing="0" border="1"><tr><th>関数名</th>
<td colspan="4">int foo_send(const unsigned char *buf, unsigned bytes)</td></tr>
<tr><th>説明</th>
<td colspan="4">データ送信開始</td></tr>
<tr><td colspan="5"><b>引数</b></td></tr>
<tr><th>項番</th>
<th>仮引数名</th>
<th>型</th>
<th colspan="2">説明</th></tr>
<tr><td>1</td>
<td>buf</td>
<td>const unsigned char *</td>
<td colspan="2">送信するデータの先頭アドレス</td></tr>
<tr><td>2</td>
<td>bytes</td>
<td>unsigned</td>
<td colspan="2">送信するデータのバイト数(最大4096*9=36Kバイトまで指定可能)</td></tr>
<tr><td colspan="5"><b>返却値</b></td></tr>
<tr><th>項番</th>
<th>型</th>
<th colspan="3">説明</th></tr>
<tr><td rowspan="5">1</td>
<td rowspan="5">int</td>
<td>0</td>
<td>FOO_OK</td>
<td>正常終了</td></tr>
<tr><td rowspan="4"><0</td>
<td>FOOO_EINVAL</td>
<td colspan="3">パラメータの値が異常である</td></tr>
<tr><td>FOO_EBUSY</td>
<td colspan="4">現在送信中である</td></tr>
<tr><td>FOO_EIO</td>
<td colspan="4">エラーが検出された</td></tr>
<tr><td>FOO_ETIMEDOUT</td>
<td colspan="4">タイムアウト発生</td></tr>
<tr><td colspan="5"><dl><dt><b>前提</b></dt>
<dd>FOOドライバが初期化されていること。すでに送信中でないこと。</dd>
<dt><b>結果</b></dt>
<dd>指定した長さのデータが、送信開始される。送信の完了はドライバ状態の通知を利用すること。</dd>
<dt><b>概略説明</b></dt>
<dd>指定されたデータを、DMA送信バッファにコピーして、送信を開始する。</dd></dl></td></tr></table>
</body></html>
todoの 「tblのセルの中の文字列で、先頭に複数の空白を含めたい」 は、「済」にしておきます。;-p)
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
details, summaryタグの「折り畳み」機能を トップページ に使ってみたく。
対応してみます。
HTML
<details> <summary> label </summary> (detail contents) </details>
YAML
- details: - summary: label - (detail contents)
という事なので、例によってあの形式を使います。
detail contens は、 swbufで出力先を切替えて溜め込んだデータを、 ペーストする事でしのぎます。
[[ details | summaryラベル | 貼り付けるバッファ名 ]]
v26.patch
diff -ur v25/ezmd.py v26/ezmd.py
--- v25/ezmd.py 2019-10-07 22:18:22.000000000 +0900
+++ v26/ezmd.py 2019-10-08 20:57:18.000000000 +0900
@@ -181,6 +181,10 @@
return outbuf.lst_get(v2)
if v1 == 'prop':
return do_prop(v1, v2)
+ if v1 == 'detail' and '|' in v2:
+ (summary, buf_name) = lst_strip( delim_pop(v2, '|') )
+ v = [ tag_new('summary', {}, summary) ] + outbuf.lst_get(buf_name)
+ return tag_new('details', {}, v)
return tag_new('a', {'href': v1}, v2) if v1 else v2
def do_br(s):
$ cat v26.patch | patch -p1
$ ./ezmd.py <<EOL | tee tmp.yaml > swbuf > buf-1 > p > foo > ul > bar > hoge > swbuf > p > [[detail | fuga | buf-1]] > EOL - p: - details: - summary: fuga - p: - foo - ul: - li /: bar - li /: hoge $ cat tmp.yaml | ./ezhtml.py <p><details><summary>fuga</summary> <p>foo</p> <ul><li>bar <li>hoge</ul></details></p>
OK
foofuga
多分影響ないはずですが、いちおう従来の確認を。
$ ./to_html.py head.yaml index.ezz.txt ezmd | diff -u index.ez.html - $ $ ./to_html.py head.yaml index-v24.txt ezmd | diff -u index-v24.html - $
OK
では早速 todo にも
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
はじめはa (href)タグのリンクのために用意した「例の形式」ですが
[[ foo | bar ]]
画像や動画用に転用
[[ img | URL ]] [[ video | URL ]]
テキストの装飾にも
[[ - | foo bar ]] [[ _ | foo bar ]] [[ / | foo bar ]]
バッファからの貼り付け
[[ paste | バッファ名 ]]
プロパティの設定
[[ prop | { li: { align: center } } ]]
折り畳みのsummary detailタグのための記述
[[ detail | ラベル | バッファ名 ]]
もう「何でもあり」になってます。
'|' 以降の箇所に、さらにこの形式の入れ子で使いたいですが...
[[ v1 | [[ va | vb ]] ]]
適当に安易に組んでるので、現状ではそれは叶いません。
def do_a_href(s): (h, t) = ('[[', ']]') (ih, it) = list( map( lambda p: s_idx(s, p), (h, t) ) ) if 0 <= ih and ih < it: s3 = lst_strip( ( s[:ih], s[ih+len(h):it], s[it+len(t):] ) ) def mcv(s): (v1, v2) = lst_strip( delim_pop(s, '|') ) if '|' in s else (s, s) return do_v1v2(v1, v2) cvs = ( (lambda s: s), mcv, do_a_href ) f = lambda i: cvs[i]( s3[i] ) return from_lst( cut_empty( flat_map( f, range(3) ) ) ) return s
do_str()から呼び出される、このdo_a_ref()での処理がネストしない前提になってます。
この関連を何とかして、ネスト可能に持っていってみます。
[[ detail | label | バッファ名 ]]
の箇所を拡張します。
detailのバッファ名の位置が文字列でない場合は、出力バッファを参照せずに、 直接その文字列以外の値を「detail」の内容として扱います。
v27.patch
diff -ur v26/ezmd.py v27/ezmd.py
--- v26/ezmd.py 2019-10-08 20:57:18.000000000 +0900
+++ v27/ezmd.py 2019-10-10 00:20:14.000000000 +0900
@@ -94,7 +94,7 @@
return { k: v_get(tag.v) }
to_lst = lambda o: o if type(o) == list else [o]
-from_lst = lambda lst: lst[0] if len(lst) == 1 else lst
+from_lst = lambda lst: lst[0] if len(lst) == 1 else ( lst if lst else '' )
flat_map = lambda f, lst: sum( map( lambda o: to_lst( f(o) ), lst ), [] )
lst_strip = lambda lst: list( map( lambda s: s.strip(), lst ) )
@@ -146,6 +146,16 @@
return lst[:1] + esc_join( lst[1:] )
s_idx = lambda s, p, dv=-1: s.index(p) if p in s else dv
+r_idx = lambda o, p, dv=-1: len(o) - 1 - s_idx( o[::-1], p ) if p in o else dv
+div_idx = lambda o, i: ( o[:i], o[i:] )
+
+def div_delim(o, delim):
+ i = s_idx(o, delim)
+ n = 1 if type(o) == list else len(delim)
+ return ( o[:i], o[i+n:] )
+
+is_str = lambda o: type(o) != list and not isinstance(o, Empty) # !!!
+lst_strip_is_str = lambda lst: list( map( lambda o: o.strip() if is_str(o) else o, lst ) )
def delim_pop(s, delim):
f = lambda lst: ( lst[0], delim.join( lst[1:] ) )
@@ -162,6 +172,23 @@
pass
return []
+def do_detail(v2):
+ if '|' in v2:
+ v2 = lst_strip_is_str( div_delim(v2, '|') )
+ elif type(v2) == list and v2 and is_str( v2[0] ) and '|' in v2[0]:
+ (a, b) = lst_strip_is_str( div_delim(v2[0], '|') )
+ v2 = ( a, ( [b] if b else [] ) + v2[1:] )
+ elif type(v2) == list and v2 and is_str( v2[-1] ) and '|' in v2[-1]:
+ (a, b) = lst_strip_is_str( div_delim(v2[-1], '|') )
+ v2 = ( v2[:-1] + ( [a] if a else [] ), b )
+ else:
+ return None
+ (summary, detail) = v2
+ if is_str(detail):
+ detail = outbuf.lst_get(detail)
+ v = [ tag_new('summary', {}, summary) ] + to_lst(detail)
+ return tag_new('details', {}, v)
+
def do_v1v2(v1, v2):
lst = ('s', 'em', 'strong', 'u', 'i', 'b')
if v1 in lst:
@@ -181,10 +208,10 @@
return outbuf.lst_get(v2)
if v1 == 'prop':
return do_prop(v1, v2)
- if v1 == 'detail' and '|' in v2:
- (summary, buf_name) = lst_strip( delim_pop(v2, '|') )
- v = [ tag_new('summary', {}, summary) ] + outbuf.lst_get(buf_name)
- return tag_new('details', {}, v)
+ if v1 == 'detail':
+ r = do_detail(v2)
+ if r:
+ return r
return tag_new('a', {'href': v1}, v2) if v1 else v2
def do_br(s):
@@ -194,19 +221,58 @@
return from_lst( cut_empty(lst) )
return s
+def get_token(s, ks):
+ idxs = list( map( lambda k: s_idx(s, k), ks ) )
+ i_s = list( filter( lambda i: idxs[i] >= 0, range( len(ks) ) ) )
+ if not i_s:
+ return ( s.strip(), '' )
+ zs = list( filter( lambda i: idxs[i] == 0, i_s ) )
+ if zs:
+ return div_idx( s, len( ks[ zs[0] ] ) )
+
+ i = min( map( lambda i: idxs[i], i_s ) )
+ (w, s) = div_idx(s, i)
+ w = w.strip()
+ return (w, s) if w else get_token(s, ks) # !
+
+def join_str(lst):
+ if len(lst) < 2:
+ return lst
+ (v, lst) = ( lst[0], join_str( lst[1:] ) )
+ if is_str(v) and lst and is_str( lst[0] ):
+ return [ v + lst[0] ] + lst[1:]
+ return [v] + lst
+
def do_a_href(s):
- (h, t) = ('[[', ']]')
- (ih, it) = list( map( lambda p: s_idx(s, p), (h, t) ) )
- if 0 <= ih and ih < it:
- s3 = lst_strip( ( s[:ih], s[ih+len(h):it], s[it+len(t):] ) )
-
- def mcv(s):
- (v1, v2) = lst_strip( delim_pop(s, '|') ) if '|' in s else (s, s)
- return do_v1v2(v1, v2)
-
- cvs = ( (lambda s: s), mcv, do_a_href )
- f = lambda i: cvs[i]( s3[i] )
- return from_lst( cut_empty( flat_map( f, range(3) ) ) )
+ def eval_targ(lst):
+ lst_ = lst[1:-1]
+ if not lst_:
+ return lst
+
+ vs = [ lst_, lst_ ] # default
+ i = s_idx(lst_, '|')
+ if i >= 0:
+ vs = [ lst_[:i], lst_[i+1:] ]
+
+ (v1, v2) = vs = list( map( from_lst, vs ) )
+ if not is_str(v1):
+ return lst
+ (v1, v2) = lst_strip_is_str(vs)
+ if type(v2) == list:
+ v2 = from_lst( join_str(v2) )
+
+ return do_v1v2(v1, v2)
+
+ if s and '[[' in s and ']]' in s:
+ lst = []
+ while s:
+ (k, s) = get_token( s, ('[[', '|', ']]') )
+ lst.append(k)
+ if k == ']]' and '[[' in lst:
+ (lst, targ) = div_idx( lst, r_idx(lst, '[[') )
+ lst = lst + to_lst( eval_targ(targ) )
+ lst = join_str(lst)
+ return from_lst(lst) if lst else []
return s
do_out_quote = lambda s: s [1:-1] if len(s) >= 2 and s[0] == s[-1] and s[0] in ("'", '"') else s
@@ -216,7 +282,7 @@
#
def map_sol(f_s_ret_sol, sol):
f = lambda o: o if isinstance(o, Empty) else f_s_ret_sol(o)
- return flat_map(f, sol) if type(sol) == list else f_s_ret_sol(sol)
+ return flat_map(f, sol) if type(sol) == list else f(sol)
def do_str(sol): # str or list
cvs = (do_out_quote, do_br, do_a_href)
$ cat v27.patch | patch -p1
変更箇所が多いです。
とりあえず動くようにだけ目指したので、かなり汚してしまったかも。
もっとシンプルに実装出来る気がするのですが...
まずは以前と同じ動作か確認。
$ ./to_html.py head.yaml index.ezz.txt ezmd | diff -u index.ez.html - $ $ ./to_html.py head.yaml index-v24.txt ezmd | diff -u index-v24.html - $ $ ./to_html.py head.yaml index-v26.txt ezmd | diff -u index-v26.html - $ $ ./to_html.py head.yaml ex_tbl.txt ex_tbl | diff -u ex_tbl.html - | nkf -u --- ex_tbl.html 2019-10-07 18:07:10.000000000 +0900 +++ - 2019-10-09 23:08:53.000000000 +0900 @@ -19,7 +19,7 @@ <h1><a name="c_1_0">表のサンプル</a></h1> <h3><a name="c_3_1">midiのときの表</a></h3> <p><a href="http://kondoh.html.xdomain.jp/midi.html#smf_outline">SMFの構造概略</a></p> -<table cellspacing="0" border="1"><tr><th>分類</th> +<table border="1" cellspacing="0"><tr><th>分類</th> <th>種別</th> <th>データ長</th> <th>内容</th></tr> @@ -74,7 +74,7 @@ <tr><td>イベント</td> <td>可変長</td> <td colspan="2"></td></tr> -<tr><td colspan="4" align="center">:</td></tr> +<tr><td align="center" colspan="4">:</td></tr> <tr><td>デルタタイム</td> <td>可変長</td> <td colspan="2"></td></tr> @@ -86,7 +86,7 @@ <p><a href="http://kondoh.html.xdomain.jp/txtbl.html">簡単なテキストの表組みツール (C言語)</a> <br> <a href="http://kondoh.html.xdomain.jp/txtblcnt.html">TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール)</a></p> -<table cellspacing="0" border="1"><tr><th>関数名</th> +<table border="1" cellspacing="0"><tr><th>関数名</th> <td colspan="4">int foo_send(const unsigned char *buf, unsigned bytes)</td></tr> <tr><th>説明</th> <td colspan="4">データ送信開始</td></tr>
最後のは環境の違いによるもので、 辞書の順番の違いで、プロパティの指定順が入れ替わってます。
これは想定内でOK
$ ./ezmd.py <<EOL > [[foo| [[bar|hoge]] ]] > EOL - p: - a href="foo": a href="bar": hoge $ ./ezmd.py <<EOL > [[detail| label | [[img|foo]] ]] > EOL - p: - details: - summary: label - img src="foo": / $ ./ezmd.py <<EOL > [[detail| [[img|foo]] | [[img|bar]] ]] > EOL - p: - details: - summary: - img src="foo": / - img src="bar": /
一応、思惑通り。
果たしてHTMLで、label が画像とかできるのだろうか?
foo
今使ってるブラウザはSafariですが、いけてます。(^_^v
あと一声、出力バッファからペースせず、この「例の形式」でpタグやulタグを生成したいところ。
トップページ でも使ってみましょう。
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
「例の形式」であるところの
[[ v1 | v2 ]]
は
に変換されて(do_v1v2()関数)、後続の処理に渡ります。
バージョン27 例の形式の入れ子 で、v2 の箇所にさらに入れ子で「例の形式」を記述可能にしました。
ですが、v2の位置にpタグやulタグを配置しようとしても、直接記述する事はできません。
トップレベルのモードをpモードやulモードに遷移させねばならず、 予め、出力バッファを切替えておいて、そこにデータを溜めておく必要があります。
そのデータが溜ってるバッファを指定して
[[ v1 | [[ paste | バッファ名 ]] ]]
などと貼り付けていました。 バージョン22 バッファに出力してからペースト
面倒です。
どうにか、v2 の位置に直接記述したいところ...
本ツールが最終的に出力するYAML形式のデータは、 簡易なHTMLパーサ 2018秋 が、入力データとして処理する形式です。
ならば、このYAML形式のデータをv2の位置に記述してしまえばいいのでは?
本ツールでは、タグの内部形式のデータを
def tag_to_dic(tag): pstr = lambda k, v: '{}="{}"'.format(k, v) if v != None else k lst = [ tag.name ] + list( map( lambda kv: pstr(*kv), tag.prop.items() ) ) k = ' '.join(lst) def v_get(v): if type(v) == list: return list( map(v_get, v) ) if isinstance(v, Empty): return tag_to_dic(v) return v return { k: v_get(tag.v) }
この関数で辞書に変換します。
最後に
: lst = list( map( tag_to_dic, lst ) ) u8 = yaml_dump(lst) :
タグのリストを辞書のリストにして、YAML形式で出力してます。
例えば「例の形式」のv1が'yaml'ならば、v2のテキストをYAML形式としてyaml.load()。
特別なタグ名'yaml'として tag_new( 'yaml', {}, v=yaml.load()結果 ) として内部データで保持。
tag_to_dic()関数の変換で、タグの名前が'yaml'の場合は特別扱いして、 保持してる、yaml.load()結果のデータを返すようにします。
yaml.load()結果は、辞書かリストが返るとして...
現状の呼び出し側では、辞書が返る事だけを期待てるので、修正が必要です。
この方針で何とかしてみましょう。
「例の形式」でYAMLデータを記述する場合
[[ yaml | YAMLデータ ]]
YAMLデータは当然、 簡易なHTMLパーサ 2018秋 が期待する「くせ」のある形式です。
例えば
[[ yaml | {p: [foo, bar]} ]] [[ yaml | [{p: [foo, bar]}, {p: hoge}] ]] [[ yaml | {ul: [{li /: hoge}, {li /: fuga}]} ]] [[ yaml | [ {p: [foo, bar]}, {ul: [{li /: hoge}, {li /: fuga}]} ] ]]
のような感じ。
v28.patch
diff -ur v27/ezmd.py v28/ezmd.py
--- v27/ezmd.py 2019-10-10 00:20:14.000000000 +0900
+++ v28/ezmd.py 2019-10-10 23:57:05.000000000 +0900
@@ -85,16 +85,17 @@
k = ' '.join(lst)
def v_get(v):
- if type(v) == list:
- return list( map(v_get, v) )
- if isinstance(v, Empty):
+ if is_lst(v):
+ #return list( map(v_get, v) )
+ return flat_map(v_get, v)
+ if is_tag(v):
return tag_to_dic(v)
return v
- return { k: v_get(tag.v) }
+ return tag.v if tag.name == 'yaml' else { k: v_get(tag.v) }
-to_lst = lambda o: o if type(o) == list else [o]
-from_lst = lambda lst: lst[0] if len(lst) == 1 else ( lst if lst else '' )
+to_lst = lambda o: o if is_lst(o) else [o]
+from_lst = lambda lst: lst[0] if len(lst) == 1 else lst
flat_map = lambda f, lst: sum( map( lambda o: to_lst( f(o) ), lst ), [] )
lst_strip = lambda lst: list( map( lambda s: s.strip(), lst ) )
@@ -151,15 +152,18 @@
def div_delim(o, delim):
i = s_idx(o, delim)
- n = 1 if type(o) == list else len(delim)
+ n = 1 if is_lst(o) else len(delim)
return ( o[:i], o[i+n:] )
-is_str = lambda o: type(o) != list and not isinstance(o, Empty) # !!!
+is_lst = lambda o: type(o) == list
+is_tag = lambda o: isinstance(o, Empty) # !!!
+is_str = lambda o: not is_lst(o) and not is_tag(o)
lst_strip_is_str = lambda lst: list( map( lambda o: o.strip() if is_str(o) else o, lst ) )
-def delim_pop(s, delim):
- f = lambda lst: ( lst[0], delim.join( lst[1:] ) )
- return f( s.split(delim) )
+def delim_pop(o, delim):
+ if delim in o:
+ return div_delim(o, delim)
+ return ( o, [] if is_lst(o) else '' )
def do_prop(v1, v2):
tag_props.clear()
@@ -172,21 +176,23 @@
pass
return []
-def do_detail(v2):
- if '|' in v2:
- v2 = lst_strip_is_str( div_delim(v2, '|') )
- elif type(v2) == list and v2 and is_str( v2[0] ) and '|' in v2[0]:
- (a, b) = lst_strip_is_str( div_delim(v2[0], '|') )
- v2 = ( a, ( [b] if b else [] ) + v2[1:] )
- elif type(v2) == list and v2 and is_str( v2[-1] ) and '|' in v2[-1]:
- (a, b) = lst_strip_is_str( div_delim(v2[-1], '|') )
- v2 = ( v2[:-1] + ( [a] if a else [] ), b )
- else:
- return None
+def do_detail(o):
+ v2 = []
+ if is_str(o) and '|' in o:
+ v2 = lst_strip( div_delim(o, '|') )
+ elif is_lst(o):
+ i_s = list( filter( lambda i: is_str(o[i]) and '|' in o[i], range( len(o) ) ) )
+ if i_s:
+ i = i_s[0]
+ (h, t) = div_delim( o[i], '|' )
+ v2 = ( join_o( o[:i], h ), join_o( t, o[i+1:] ) )
+ if len(v2) != 2:
+ return []
+
(summary, detail) = v2
if is_str(detail):
detail = outbuf.lst_get(detail)
- v = [ tag_new('summary', {}, summary) ] + to_lst(detail)
+ v = join_o( tag_new('summary', {}, summary), detail )
return tag_new('details', {}, v)
def do_v1v2(v1, v2):
@@ -208,6 +214,8 @@
return outbuf.lst_get(v2)
if v1 == 'prop':
return do_prop(v1, v2)
+ if v1 == 'yaml':
+ return tag_new( 'yaml', {}, yaml.load(v2) )
if v1 == 'detail':
r = do_detail(v2)
if r:
@@ -235,44 +243,63 @@
w = w.strip()
return (w, s) if w else get_token(s, ks) # !
-def join_str(lst):
- if len(lst) < 2:
- return lst
- (v, lst) = ( lst[0], join_str( lst[1:] ) )
- if is_str(v) and lst and is_str( lst[0] ):
- return [ v + lst[0] ] + lst[1:]
- return [v] + lst
+def join_o(a, b):
+ if is_str(a) and is_str(b):
+ return a + b
+ (a, b) = map( lambda o: o.strip() if is_str(o) else o, (a, b) )
+ (a, b) = map( lambda o: [] if o == '' else to_lst(o), (a, b) )
+ return from_lst(a + b)
+
+def try_a_href(s): # (o, t)
+ s_ = s[ len('[['): ]
+ (i_a, i_b, i_c) = map( lambda p: s_idx(s_, p), ('[[', '|', ']]') )
+ if i_c < 0:
+ return (s, '')
+ if i_c < i_b:
+ i_b = -1
+ if i_a >= 0 and i_a < (i_c if i_b < 0 else i_b):
+ return ('[[', s_)
+
+ if i_b < 0:
+ (h, t) = div_delim(s_, ']]')
+ v = h.strip()
+ return ( do_v1v2(v, v), t )
+
+ (h, t) = div_delim(s_, '|')
+ v1 = h.strip()
+ if i_a < 0:
+ (h, t) = div_delim(t, ']]')
+ v2 = h.strip()
+ return ( do_v1v2(v1, v2), t )
+
+ o = do_a_href(t)
+ if is_tag(o):
+ return ('[[', s_)
+
+ if is_str(o):
+ if ']]' not in o:
+ return (s, '')
+ (h, t) = div_delim(o, ']]')
+ v2 = h.strip()
+ return ( do_v1v2(v1, v2), t )
+
+ # o is list
+ for i in range( len(o) ):
+ o_ = o[i]
+ if is_str(o_) and ']]' in o_:
+ (h, t) = div_delim(o_, ']]')
+ v2 = join_o( o[:i], h )
+ r = do_v1v2(v1, v2)
+ r = join_o( r, join_o( t, o[i+1:] ) )
+ return (r, '')
+ return ('[[', s_)
def do_a_href(s):
- def eval_targ(lst):
- lst_ = lst[1:-1]
- if not lst_:
- return lst
-
- vs = [ lst_, lst_ ] # default
- i = s_idx(lst_, '|')
- if i >= 0:
- vs = [ lst_[:i], lst_[i+1:] ]
-
- (v1, v2) = vs = list( map( from_lst, vs ) )
- if not is_str(v1):
- return lst
- (v1, v2) = lst_strip_is_str(vs)
- if type(v2) == list:
- v2 = from_lst( join_str(v2) )
-
- return do_v1v2(v1, v2)
-
- if s and '[[' in s and ']]' in s:
- lst = []
- while s:
- (k, s) = get_token( s, ('[[', '|', ']]') )
- lst.append(k)
- if k == ']]' and '[[' in lst:
- (lst, targ) = div_idx( lst, r_idx(lst, '[[') )
- lst = lst + to_lst( eval_targ(targ) )
- lst = join_str(lst)
- return from_lst(lst) if lst else []
+ if '[[' in s:
+ (h, t) = div_delim(s, '[[')
+ (o, t) = try_a_href('[[' + t)
+ r = join_o(h, o)
+ return join_o( r, do_a_href(t) ) if t else r
return s
do_out_quote = lambda s: s [1:-1] if len(s) >= 2 and s[0] == s[-1] and s[0] in ("'", '"') else s
@@ -281,8 +308,8 @@
# sol : str or lst
#
def map_sol(f_s_ret_sol, sol):
- f = lambda o: o if isinstance(o, Empty) else f_s_ret_sol(o)
- return flat_map(f, sol) if type(sol) == list else f(sol)
+ f = lambda o: o if is_tag(o) else f_s_ret_sol(o)
+ return flat_map(f, sol) if is_lst(sol) else f(sol)
def do_str(sol): # str or list
cvs = (do_out_quote, do_br, do_a_href)
@@ -322,7 +349,7 @@
def fs(s):
sol = do_str(s)
return tag_new( 'li', {'/': None}, sol ) if sol != [] else []
- f = lambda o: lst_to(o) if type(o) == list else fs(o)
+ f = lambda o: lst_to(o) if is_lst(o) else fs(o)
lst = list( flat_map(f, lst) )
return tag_new('ul', {}, lst)
@@ -426,9 +453,9 @@
def li_to_name_v(o):
dv = ('td', o)
- if not o or isinstance(o, Empty):
+ if not o or is_tag(o):
return dv
- if type(o) == list:
+ if is_lst(o):
(name, v) = li_to_name_v( o[0] )
return ( name, [v] + o[1:] )
return ( 'th', o[2:] ) if o.startswith('||') else dv
@@ -637,7 +664,7 @@
lst = list( map( strip_tail, lst ) )
lst = ezmd(lst)
- lst = list( map( tag_to_dic, lst ) )
+ lst = flat_map( tag_to_dic, lst )
u8 = yaml_dump(lst)
b = nkf.cvt(u8, nkf_opt) if nkf_opt != '-u' else u8
$ cat v28.patch | patch -p1
前回の バージョン27 例の形式の入れ子 での実装も見直して、修正してみました。
(あまり改善されてない気もしますが...)
$ ./to_html.py head.yaml index.ezz.txt ezmd | diff -u index.ez.html - $ $ ./to_html.py head.yaml index-v24.txt ezmd | diff -u index-v24.html - $ $ ./to_html.py head.yaml index-v26.txt ezmd | diff -u index-v26.html - $ $ ./to_html.py head.yaml ex_tbl.txt ex_tbl | diff -u ex_tbl.html - | nkf -u --- ex_tbl.html 2019-10-07 18:07:10.000000000 +0900 +++ - 2019-10-11 00:04:07.000000000 +0900 @@ -19,7 +19,7 @@ <h1><a name="c_1_0">表のサンプル</a></h1> <h3><a name="c_3_1">midiのときの表</a></h3> <p><a href="http://kondoh.html.xdomain.jp/midi.html#smf_outline">SMFの構造概略</a></p> -<table cellspacing="0" border="1"><tr><th>分類</th> +<table border="1" cellspacing="0"><tr><th>分類</th> <th>種別</th> <th>データ長</th> <th>内容</th></tr> @@ -74,7 +74,7 @@ <tr><td>イベント</td> <td>可変長</td> <td colspan="2"></td></tr> -<tr><td colspan="4" align="center">:</td></tr> +<tr><td align="center" colspan="4">:</td></tr> <tr><td>デルタタイム</td> <td>可変長</td> <td colspan="2"></td></tr> @@ -86,7 +86,7 @@ <p><a href="http://kondoh.html.xdomain.jp/txtbl.html">簡単なテキストの表組みツール (C言語)</a> <br> <a href="http://kondoh.html.xdomain.jp/txtblcnt.html">TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール)</a></p> -<table cellspacing="0" border="1"><tr><th>関数名</th> +<table border="1" cellspacing="0"><tr><th>関数名</th> <td colspan="4">int foo_send(const unsigned char *buf, unsigned bytes)</td></tr> <tr><th>説明</th> <td colspan="4">データ送信開始</td></tr>
例によって、最後の結果は想定内でOK。
仕様の箇所のサンプルから。
$ ./ezmd.py <<EOL > [[ yaml | {p: [foo, bar]} ]] > EOL - p: - p: - foo - bar $ ./ezmd.py <<EOL > [[ yaml | [{p: [foo, bar]}, {p: hoge}] ]] > EOL - p: - p: - foo - bar - p: hoge $ ./ezmd.py <<EOL > [[ yaml | {ul: [{li /: hoge}, {li /: fuga}]} ]] > EOL - p: - ul: - li /: hoge - li /: fuga $ ./ezmd.py <<EOL > [[ yaml | [ {p: [foo, bar]}, {ul: [{li /: hoge}, {li /: fuga}]} ] ]] > EOL - p: - p: - foo - bar - ul: - li /: hoge - li /: fuga
うーむ。デフォルトpモードなので、pタグがネストしてしまった...
素のpモードの上での、pタグの例が悪かったですね。
$ ./ezmd.py <<EOL [[ detail | foo | [[ yaml | [{p: bar}, {p: hoge}] ]] ]] EOL - p: - details: - summary: foo - p: bar - p: hoge
bar hogefoo
$ ./ezmd.py <<EOL > [[ detail | foo | [[ yaml | {ul: [{li /: bar}, {li /: hoge}]} ]] ]] > EOL - p: - details: - summary: foo - ul: - li /: bar - li /: hoge
foo
日本語
OK
しかし「例の形式」は改行を許さず、1行で記述せねばなりません。
例えば、以下のtodoリストのulタグを、1行のYAML形式で書くのは、さすがに至難の技です。
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
バージョン28 例の形式でpタグやulタグ では「例の形式」
[[ v1 | v2 ]]
に対して
[[ yaml | ezhtmlのYAML形式 ]]
で、v2にどんなタグでも記述できるべく対応してみましたが...
ょっと凝ったタグを使おうとすると、 v2箇所が横に長〜い記述になってしまいます。
「例の形式」の途中に改行を含める事は許されません。
なんとか、改行を入れる事はできないか...
これまでに、ulモードの処理と、tbl_orgモードの処理で、 同様に横に長〜くなるのを嫌って、改行を許すように手を入れてました。
改行の前に'\'を入れた場合、改行をエスケープさせて、2つの行を連結してました。
まず、これらのモードだけの対応にせずに、根本的な部分に処理を追加します。
そもそも
if __name__ == "__main__": b = nkf.get_stdin() (s, nkf_opt) = nkf.to_str(b) lst = s.split('\n') lst = list( map( strip_tail, lst ) ) lst = ezmd(lst) lst = flat_map( tag_to_dic, lst ) :
ここで、標準入力からの文字列の塊を、 改行ごとに行に分けてリストlstにしてます。
この段階で、改行の前にエスケープ・コード'\'があると、 行に分けずに'\'だけ削除する事にします。
これで、
となります。
ulモードとtbl_orgモードでは、 従来の処理互換のため、行を連結してた箇所で、行の中の改行は削除します。
これで例えば
p foo [[ bar | \ line-1 \ line-2 \ line-3 \ : line-n \ ]]
などと記述しても、従来の行文字列の処理箇所には
p foo [[ bar | line-1 改行 line-2 改行 line-3 改行 ... 改行 line-n ]]
という、複数の改行コードを含む「1本の文字列」が渡るはずです。
さて、ここから
line-1 改行 line-2 改行 line-3 改行 ... 改行 line-n
の文字列。
これは、標準入力から受け取った文字列と、同じ形式と見なせるはず。
ここから何とか、呼び出しを「でんぐり返して」
if __name__ == "__main__": b = nkf.get_stdin() (s, nkf_opt) = nkf.to_str(b) lst = s.split('\n') lst = list( map( strip_tail, lst ) ) lst = ezmd(lst) lst = flat_map( tag_to_dic, lst ) :
この辺りに喰わせるように持っていければ「めでたしめでたし」なのでは?
「例の形式」にでんぐり返し処理用のものを追加します。
[[ mode | xxx ]]
xxxは改行込みの文字列を想定しているので、使う場合は実質
[[ mode | \ xxx\ yyy\ : zzz\ ]]
と、なりましょうや。
ですが、ここからの実装が「いばらの道」でした。
腐心しつつ、あれこれ試した結果、少々あきらめて折衷案的なものに落ち着きました。
[[ mode | ^...$ ]]
modeのときはv2の先頭と末尾には^と$を追加します。
v2として処理するのは、当然...の中身の部分だけです。
...の中で'$'を使いたいときは'\$'で、エスケープします。
これで、... の中で
...[[ ... ]] ...
などとネストしてても、 一発で'$'までを文字列として取り出して処理します。
使うときは実質
[[ mode | ^\ line-1 \ line-2 \ [[ foo | bar ]] \ line-3 \ $ ]]
な感じになります。
v29.patch
diff -ur v28/ezmd.py v29/ezmd.py
--- v28/ezmd.py 2019-10-10 23:57:05.000000000 +0900
+++ v29/ezmd.py 2019-10-12 01:02:02.000000000 +0900
@@ -138,13 +138,20 @@
return e.to_attr( locals() )
-def esc_join(lst):
- if len(lst) < 2:
- return lst
- if lst[0] and lst[0][-1] == '\\':
- lst = [ strip_tail( lst[0][:-1] ) + strip_head( lst[1] ) ] + lst[2:]
- return esc_join(lst)
- return lst[:1] + esc_join( lst[1:] )
+def rm_nl(s):
+ if '\n' in s:
+ (h, t) = div_delim(s, '\n')
+ return strip_tail(h) + rm_nl( strip_head(t) )
+ return s
+
+def esc_join(lst, delim):
+ buf = []
+ for s in lst:
+ if buf and buf[-1] and buf[-1][-1] == '\\':
+ buf[-1] = buf[-1][:-1] + delim + s
+ else:
+ buf.append(s)
+ return buf
s_idx = lambda s, p, dv=-1: s.index(p) if p in s else dv
r_idx = lambda o, p, dv=-1: len(o) - 1 - s_idx( o[::-1], p ) if p in o else dv
@@ -196,6 +203,12 @@
return tag_new('details', {}, v)
def do_v1v2(v1, v2):
+ if ' ' in v1:
+ lst = v1.split(' ')
+ lst = lst_strip(lst)
+ lst = cut_empty(lst)
+ (v1, args) = ( lst[0] if lst else '', lst[1:] )
+
lst = ('s', 'em', 'strong', 'u', 'i', 'b')
if v1 in lst:
return tag_new(v1, {}, v2)
@@ -216,6 +229,10 @@
return do_prop(v1, v2)
if v1 == 'yaml':
return tag_new( 'yaml', {}, yaml.load(v2) )
+ if v1 == 'mode':
+ outbuf.push_tmp()
+ s_to_tag_lst(v2)
+ return outbuf.pop_tmp()
if v1 == 'detail':
r = do_detail(v2)
if r:
@@ -250,6 +267,14 @@
(a, b) = map( lambda o: [] if o == '' else to_lst(o), (a, b) )
return from_lst(a + b)
+def hat_dollar(s):
+ s_ = strip_head(s)
+ if s_ and s_[0] == '^':
+ i = s_idx(s_, '$')
+ if i > 0 and s_[i-1] != '\\':
+ return ( s_[1:i], s_[i+1:] )
+ return ('', s)
+
def try_a_href(s): # (o, t)
s_ = s[ len('[['): ]
(i_a, i_b, i_c) = map( lambda p: s_idx(s_, p), ('[[', '|', ']]') )
@@ -270,6 +295,14 @@
if i_a < 0:
(h, t) = div_delim(t, ']]')
v2 = h.strip()
+ v2 = ''.join( hat_dollar(v2) )
+ return ( do_v1v2(v1, v2), t )
+
+ (h, t) = hat_dollar(t)
+ if h:
+ v2 = h
+ (h, t) = div_delim(t, ']]')
+ # h ...
return ( do_v1v2(v1, v2), t )
o = do_a_href(t)
@@ -318,7 +351,7 @@
return sol
def do_mode_ul(buf):
- buf = esc_join(buf)
+ buf = list( map(rm_nl, buf) )
buf = list( filter( lambda s: s.strip(), buf ) )
buf = list( map(idt_cnt, buf) ) # (i, s)
@@ -418,7 +451,7 @@
tbl_prop = { 'border': 1, 'cellspacing': 0 }
def do_tbl_org(buf):
- buf = esc_join(buf)
+ buf = list( map(rm_nl, buf) )
buf = lst_strip(buf)
buf = cut_empty(buf)
if buf:
@@ -646,6 +679,18 @@
res = do_index(hd_names)
return res
+def pre_split_esc_join(s, delim):
+ buf = s.split(delim)
+
+ lst = []
+ is_call = lambda e: e.s in ('pre', '/')
+ func = lambda e: lst.append(e.tmp)
+ e = buf_loop_new(buf, is_call, func)
+ e.run()
+
+ f = lambda buf: buf if buf and buf[0] == 'pre' else esc_join(buf, delim)
+ return sum( map(f, lst), [] )
+
def yaml_dump(o):
def represent_str(dumper, instance):
tag = 'tag:yaml.org,2002:str'
@@ -657,13 +702,17 @@
return yaml.dump( o, default_flow_style=False, allow_unicode=True, encoding='utf-8' )
+def s_to_tag_lst(s):
+ lst = pre_split_esc_join(s, '\n')
+ lst = list( map( strip_tail, lst ) )
+ lst = ezmd(lst)
+ return lst
+
if __name__ == "__main__":
b = nkf.get_stdin()
(s, nkf_opt) = nkf.to_str(b)
- lst = s.split('\n')
- lst = list( map( strip_tail, lst ) )
- lst = ezmd(lst)
+ lst = s_to_tag_lst(s)
lst = flat_map( tag_to_dic, lst )
u8 = yaml_dump(lst)
$ cat v29.patch | patch -p1
腐心してなんとか実装しました。
(ですが、多少の敗北感はいなめない...)
$ ./to_html.py head.yaml index-v28.txt ezmd | diff -u index-v28.html - $ $ ./to_html.py head.yaml ex_tbl.txt ex_tbl | diff -u ex_tbl.html - | nkf -u --- ex_tbl.html 2019-10-07 18:07:10.000000000 +0900 +++ - 2019-10-12 01:04:18.000000000 +0900 @@ -19,7 +19,7 @@ <h1><a name="c_1_0">表のサンプル</a></h1> <h3><a name="c_3_1">midiのときの表</a></h3> <p><a href="http://kondoh.html.xdomain.jp/midi.html#smf_outline">SMFの構造概略</a></p> -<table cellspacing="0" border="1"><tr><th>分類</th> +<table border="1" cellspacing="0"><tr><th>分類</th> <th>種別</th> <th>データ長</th> <th>内容</th></tr> @@ -74,7 +74,7 @@ <tr><td>イベント</td> <td>可変長</td> <td colspan="2"></td></tr> -<tr><td colspan="4" align="center">:</td></tr> +<tr><td align="center" colspan="4">:</td></tr> <tr><td>デルタタイム</td> <td>可変長</td> <td colspan="2"></td></tr> @@ -86,7 +86,7 @@ <p><a href="http://kondoh.html.xdomain.jp/txtbl.html">簡単なテキストの表組みツール (C言語)</a> <br> <a href="http://kondoh.html.xdomain.jp/txtblcnt.html">TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール)</a></p> -<table cellspacing="0" border="1"><tr><th>関数名</th> +<table border="1" cellspacing="0"><tr><th>関数名</th> <td colspan="4">int foo_send(const unsigned char *buf, unsigned bytes)</td></tr> <tr><th>説明</th> <td colspan="4">データ送信開始</td></tr>
OK
このページ自身に
[[ #c_v28 | [[ mode | ^\ ul \ バージョン \ 28 \ 例の形式で \ pタグや \ ulタグ \ $ ]] ]]
などと記述してみると
上記のように。
ulタグ全体が、1つのリンクになってしまいました。
同様に
[[ #c_v28 | [[ mode | ^\ tbl \ tbl_ul \ バージョン \ 28 \ 例の形式で \ pタグや \ ulタグ \ $ ]] ]]
では
バージョン | 28 |
例の形式で | |
pタグや | |
ulタグ |
表全体が1つのリンク。
使うかどうかは別として、こういう事も記述できます、という事で。
バージョン28 例の形式でpタグやulタグ で試したYAML形式の場合と、同様の結果が得られる記述が可能か、試しておきます。
$ ./ezmd.py <<EOL > [[ yaml | {p: [foo, bar]} ]] > EOL - p: - p: - foo - bar
この場合は
$ ./ezmd.py <<EOL > [[ mode | ^\\ > p \\ > foo \\ > bar \\ > $ ]] > EOL - p: - p: - foo - bar
OK
ヒアドキュメントの都合で行末の'\'は'\\'にしてます。
$ ./ezmd.py <<EOL > [[ yaml | [{p: [foo, bar]}, {p: hoge}] ]] > EOL - p: - p: - foo - bar - p: hoge
だと
$ ./ezmd.py <<EOL > [[ mode | ^\\ > p \\ > foo \\ > bar \\ > \\ > hoge \\ > $ ]] > EOL - p: - p: - foo - bar - p: - hoge
OK
$ ./ezmd.py <<EOL > [[ yaml | {ul: [{li /: hoge}, {li /: fuga}]} ]] > EOL - p: - ul: - li /: hoge - li /: fuga
では
$ ./ezmd.py <<EOL > [[ mode | ^\\ > ul \\ > hoge \\ > fuga \\ > $ ]] > EOL - p: - ul: - li /: hoge - li /: fuga
OK
$ ./ezmd.py <<EOL > [[ yaml | [ {p: [foo, bar]}, {ul: [{li /: hoge}, {li /: fuga}]} ] ]] > EOL - p: - p: - foo - bar - ul: - li /: hoge - li /: fuga
も
$ ./ezmd.py <<EOL > [[ mode | ^\\ > p \\ > foo \\ > bar \\ > ul \\ > hoge \\ > fuga \\ > $ ]] > EOL - p: - p: - foo - bar - ul: - li /: hoge - li /: fuga
このとおり。
$ ./ezmd.py <<EOL [[ detail | foo | [[ yaml | [{p: bar}, {p: hoge}] ]] ]] EOL - p: - details: - summary: foo - p: bar - p: hoge
はどうか?
$ ./ezmd.py <<EOL > [[ detail | foo | [[ mode | ^\\ > p \\ > bar \\ > \\ > hoge \\ > $ ]] ]] > EOL - p: - details: - summary: foo - p: - bar - p: - hoge
うーむ。ちょっと違うけど、この違いは「いたしかた無し」かも。
bar hogefoo
まぁHTMLでは、多分同じですね。
$ ./ezmd.py <<EOL > [[ detail | foo | [[ yaml | {ul: [{li /: bar}, {li /: hoge}]} ]] ]] > EOL - p: - details: - summary: foo - ul: - li /: bar - li /: hoge
$ ./ezmd.py <<EOL > [[ detail | foo | [[ mode | ^\\ > ul \\ > bar \\ > hoge \\ > $ ]] ]] > EOL - p: - details: - summary: foo - ul: - li /: bar - li /: hoge
これは一致。OKです。
[[ detail | 日本語 | [[ yaml | {ul: [{li /: ひらがな}, {li /: カタカナ}]} ]] ]]
日本語の場合も
[[ detail | 日本語 | [[ mode | ^\ ul \ ひらがな \ カタカナ \ $ ]] ]]
日本語
OK
テキストが横に長〜くならずに、同様の結果を得られます。
これで、出力バッファを切り替えて予め作成したタグを、 後ろの方で貼り付けずに済みます。
テキストの段階で、多少見通しが良くなります。
ではさっそくtodoでも使ってみます。
[[detail| todo | [[mode| ^\ ul \ [[-|h1, h2, h3, ...]] \ [[-|p]] \ [[-|pre]] \ [[-|ul, li]] \ [[-|a (href)]] \ [[-|hr]] \ [[-|img]] \ [[-|video] ] \ [[-|s]] \ [[-|目次機能]] \ [[-|headタグのtitleを何とかする]] \ [[-|バグ修正と調整]] \ [[-|br]] \ [[-|dl]] \ [[-|table]] \ [[-|ulからtableへの変換]] \ [[-|tblのセルの中の文字列で、先頭に複数の空白を含めたい]] \ [[-|tbl_ulモードでthタグも]] \ [[-|a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい]] \ [[-|a (name)]] \ [[-|h1,h2,h3で後に空行あったらデフォルトのpモードに]] \ [[-|モード遷移のバグ修正]] \ [[-|プロパティを細かく指定出来るように]] \ [[-|打ち消し線以外にも文字列の装飾を]] \ [[-|折り畳み]] \ [[-|例の形式の入れ子]] \ [[-|例の形式で簡単なpタグやulタグを生成できないものか]] \ [[-|例の形式で改行を許せぬものか]] \ ulで改行が消える不具合 \ $ ]] ]]
のテキストの結果が、以下の内容です。
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
前回の バージョン29 例の形式で改行を許すように でバグがありました。
元々行末の'\'で行を連結してたulモードとtbl_orgモードの処理箇所で、 rm_nl()に置き換えて、改行を消すようにしました。
単純に置き換えたのが、まずかったです。
$ ./ezmd.py <<EOL > ul > foo > bar > [[ hoge | fuga ]] > EOL - ul: - li /: foo - li /: bar - li /: a href="hoge": fuga
例えば上記のulタグ。
最後のリンクの箇所をmodeの形式に置き換えて、 別のulタグを生成しようとすると...
$ ./ezmd.py <<EOL > ul > foo > bar > [[ mode | ^\\ > ul \\ > hoge \\ > fuga \\ > $ ]] > EOL - ul: - li /: foo - li /: bar - li /: p: - ulhogefuga
後者のulタグに必要な改行
'ul 改行 hoge 改行 fuga'
が、前者のulタグの処理で、先に削除されてしまい
'ulhogefuga'
の文字列になってしまってます。
改行の削除を、ulモードとtbl_orgモードだけで、個別にするのをやめます。
とりあえず改行込みで処理してしまってから、 最後に不要な改行を、一括しえ削除するようにします。
preタグの中は「聖域」なので、改行削除の手出しは無用です。
v30.patch
diff -ur v29/ezmd.py v30/ezmd.py
--- v29/ezmd.py 2019-10-12 01:02:02.000000000 +0900
+++ v30/ezmd.py 2019-10-12 11:36:46.000000000 +0900
@@ -351,7 +351,6 @@
return sol
def do_mode_ul(buf):
- buf = list( map(rm_nl, buf) )
buf = list( filter( lambda s: s.strip(), buf ) )
buf = list( map(idt_cnt, buf) ) # (i, s)
@@ -451,7 +450,6 @@
tbl_prop = { 'border': 1, 'cellspacing': 0 }
def do_tbl_org(buf):
- buf = list( map(rm_nl, buf) )
buf = lst_strip(buf)
buf = cut_empty(buf)
if buf:
@@ -702,10 +700,21 @@
return yaml.dump( o, default_flow_style=False, allow_unicode=True, encoding='utf-8' )
+def rm_nl_tag(o):
+ if is_str(o):
+ return rm_nl(o)
+ if is_lst(o):
+ return list( map(rm_nl_tag, o) )
+ # o is tag
+ if o.name != 'pre':
+ o.v = rm_nl_tag(o.v)
+ return o
+
def s_to_tag_lst(s):
lst = pre_split_esc_join(s, '\n')
lst = list( map( strip_tail, lst ) )
lst = ezmd(lst)
+ lst = list( map( rm_nl_tag, lst) )
return lst
if __name__ == "__main__":
$ cat v30.patch | patch -p1
$ ./to_html.py head.yaml index-v29.txt ezmd | diff -u index-v29.html - $
OK
$ ./ezmd.py <<EOL > ul > foo > bar > [[ mode | ^\\ > ul \\ > hoge \\ > fuga \\ > $ ]] > EOL - ul: - li /: foo - li /: bar - li /: ul: - li /: hoge - li /: fuga
OK
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
include機能を追加してみます。
[[ include | URLかファイルのパス ]]
「URLかファイルのパス」の中身は、本ツールの期待する形式のテキストデータです。
v31.patch
diff -ur v30/ezmd.py v31/ezmd.py
--- v30/ezmd.py 2019-10-12 11:36:46.000000000 +0900
+++ v31/ezmd.py 2019-10-12 16:46:42.000000000 +0900
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+import subprocess
import yaml
import six
import nkf
@@ -202,6 +203,13 @@
v = join_o( tag_new('summary', {}, summary), detail )
return tag_new('details', {}, v)
+def text_get(s):
+ ps = ('http', 'https')
+ cmd = 'wget -q -O-' if any( map( lambda p: s.startswith(p + '://'), ps ) ) else 'cat'
+ b = subprocess.check_output( cmd + ' ' + s, shell=True )
+ (s, nkf_opt) = nkf.to_str(b)
+ return s
+
def do_v1v2(v1, v2):
if ' ' in v1:
lst = v1.split(' ')
@@ -229,6 +237,8 @@
return do_prop(v1, v2)
if v1 == 'yaml':
return tag_new( 'yaml', {}, yaml.load(v2) )
+ if v1 == 'include':
+ return do_v1v2( 'mode', text_get(v2) )
if v1 == 'mode':
outbuf.push_tmp()
s_to_tag_lst(v2)
$ cat v31.patch | patch -p1
実装は単純です。
追加したtext_get(s)関数で、テキストデータを取得。
URLを指定する場合は wget コマンドを使ってます。
そのまま
[[ mode | テキスト ]]
の処理を利用するだけです。
$ ./to_html.py head.yaml index-v30.txt ezmd | diff -u index-v30.html - $
OK
foo_31.txt を用意しておいて...
$ cat foo_31.txt h3 foo bar ul hoge fuga
そのままincludeしてみると
$ ./ezmd.py <<EOL > [[ include | foo_31.txt ]] > EOL - p: - h3: a name="c_3_0": foo - p: - bar - ul: - li /: hoge - li /: fuga
トップレベルのpタグの配下にincludeされました。
$ ./ezmd.py <<EOL | ./ezhtml.py > [[ include | foo_31.txt ]] > EOL <p><h3><a name="c_3_0">foo</a></h3> <p>bar</p> <ul><li>hoge <li>fuga</ul></p>
確かに外側のpタグの配下に全てincludeで「含まれ」ます。
そのまま
[[ include | foo_31.txt ]]
を下記に貼り付けると
bar
上記のように。
折り畳みと組み合わせると
$ ./ezmd.py <<EOL > [[ detail | foo_31 | [[ include | foo_31.txt ]] ]] > EOL - p: - details: - summary: foo_31 - h3: a name="c_3_0": foo - p: - bar - ul: - li /: hoge - li /: fuga
テーブルの例のテキストを
[[ detail | 表の例1 | [[ include | ex_tbl_1.txt ]] ]] [[ detail | 表の例2 | [[ include | ex_tbl_2.txt ]] ]]
表の例1
分類
種別
データ長
内容 ヘッダ
ID
4バイト
"MThd" アスキー・コード 'M','T','h','d' の 4バイト サイズ
4バイト
以降のヘッダのバイト数をビッグエンディアンで格納
ヘッダの場合は値6固定なので、00,00,00,06 の4バイトフォーマットタイプ
2バイト
値0, 1, 2 のいづれかをビッグエンディアンで格納
ここではフォーマットタイプ 0 の SMF のみ扱うので、
00,00 の2バイトトラック数
2バイト
トラック数をビッグエンディアンで格納
フォーマットタイプが0の場合は、トラック数は1固定なので、
00,01 の2バイト時間分解能
2バイト
四分音符の分割数をビッグエンディアンで格納
四分音符1つをここで指定した値で分割した長さが、時間の最小単位
ただし1バイト目の最上位ビットが'1'の場合は、別の扱いとなる
ここでは1バイト目の最上位ビットが'0'のSMFのみを扱うトラック
ID
4バイト
"MTrk" アスキー・コード 'M','T','r','k' の 4バイト サイズ
4バイト
以降のトラックのバイト数をビッグエンディアンで格納 デルタタイム
可変長
イベント
可変長
デルタタイム
可変長
イベント
可変長
: デルタタイム
可変長
イベント
可変長
簡単なテキストの表組みツール (C言語)
表の例2
TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール)関数名
int foo_send(const unsigned char *buf, unsigned bytes) 説明
データ送信開始 引数 項番
仮引数名
型
説明 1
buf
const unsigned char *
送信するデータの先頭アドレス 2
bytes
unsigned
送信するデータのバイト数(最大4096*9=36Kバイトまで指定可能) 返却値 項番
型
説明 1
int
0
FOO_OK
正常終了 <0
FOOO_EINVAL
パラメータの値が異常である FOO_EBUSY
現在送信中である FOO_EIO
エラーが検出された FOO_ETIMEDOUT
タイムアウト発生
このように。
URLを指定する場合
[[ detail | 更新履歴(2019/Oct時点) | [[ include | http://kondoh.html.xdomain.jp/hist.txt ]] ]]
このように、このサイトの更新履歴を、ここに折り畳みで貼り付けてみました。
(ただし、リンクはトップページのディレクトリからの相対なので、まともに飛びません)
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
バージョン31 include でincludeに対応したので、今回はmacro変換の対応です。
変換用に「キーの文字列」から「値の文字列」に対応する辞書を用意します。
テキストの文字列を処理する前に、変換用の辞書で文字列を変換します。
変換用の辞書は、とりあえず、世界に1つだけグローバル変数で用意してみます。
macro定義用のモードを追加します。
'macro'だけの行が現れると、macro定義モードに移行します。
他のモードに切り替わるまでの間に、 YAML形式で文字列の辞書を記述します。
macro定義モードで記述された辞書は、 基本的に変換用の辞書に「追加」されます。
初期値は空の辞書で、pythonの辞書の.update()メソッドによる追加です。
同じキーのものは上書きされて更新。
辞書の内容の削除や、全体クリア処理を特別に設けるのも面倒なので...
変換辞書が更新された後、キーと値が同じものを見つけたら、 辞書から削除するようにしてみました。
文字列の変換はdo_mode()関数で、各モードの処理前に処理対象の文字列のリストに対して行ないます。
「聖域」preモードと、macroモード自体は、変換の対象外です。
できると便利そうなので、対応してみました。
変換用YAML形式の辞書を定義するときに、 変換前の文字列のキーに対して、値を文字列のリストにします。
v32.patch
diff -ur v31/ezmd.py v32/ezmd.py
--- v31/ezmd.py 2019-10-12 16:46:42.000000000 +0900
+++ v32/ezmd.py 2019-10-13 02:24:13.000000000 +0900
@@ -6,7 +6,7 @@
import nkf
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
-modes = heads + [ 'p', 'pre', 'ul', 'dl', 'tbl', 'index', 'swbuf' ]
+modes = heads + [ 'p', 'pre', 'ul', 'dl', 'tbl', 'index', 'swbuf', 'macro' ]
is_all_ge_n = lambda s, c, n: all( map( lambda c_: c_ == c, s ) ) and len(s) >= n
@@ -589,7 +589,35 @@
outbuf.append( tbls_join( outbuf.pop_tmp() ) )
+macro_dic = {}
+
+def do_macro(buf):
+ for (k, v) in macro_dic.items():
+ def f(s):
+ if k in s:
+ if is_str(v):
+ return s.replace(k, v)
+ if is_lst(v):
+ lst = list( map( lambda a: [a] if a else [], s.split(k) ) )
+ return sum( map( lambda b: b+v, lst[:-1] ), [] ) + lst[-1]
+ return s
+ buf = flat_map(f, buf)
+ return buf
+
def do_mode(mode, buf, hd_names):
+ if mode == 'macro':
+ d = yaml.load( '\n'.join(buf) )
+ if type(d) == dict:
+ cv = lambda o: list( map(cv, o) ) if is_lst(o) else str(o)
+ d = dict( map( lambda kv: list( map(cv, kv) ), d.items() ) )
+ macro_dic.update(d)
+ d = dict( filter( lambda kv: kv[0] != kv[1], macro_dic.items() ) )
+ macro_dic.clear()
+ macro_dic.update(d)
+ return
+ if mode != 'pre':
+ buf = do_macro(buf)
+
if mode in heads:
buf = lst_strip(buf)
buf = cut_empty(buf)
$ ./to_html.py head.yaml index-v31.txt ezmd | diff -u index-v31.html - $
OK
$ cat foo_32.txt macro foo: FOO bar: BAR p foo bar hoge ul foo bar hoge foobarhoge macro foo: foo p foo bar hoge ul foo bar hoge foobarhoge macro hoge: 123 p foo bar hoge ul foo bar hoge foobarhoge macro bar: bar ' bar': - ' BAR-1' - ' BAR-2' - ' BAR-3' p foo bar hoge ul foo bar hoge foobarhoge
では実行。
$ ./ezmd.py < foo_32.txt - p: - FOO BAR hoge - ul: - li /: FOO - li /: BAR - li /: hoge - li /: FOOBARhoge - p: - foo BAR hoge - ul: - li /: foo - li /: BAR - li /: hoge - li /: fooBARhoge - p: - foo BAR 123 - ul: - li /: foo - li /: BAR - li /: '123' - li /: fooBAR123 - p: - foo bar 123 - ul: - li /: foo - li /: BAR-1 - li /: BAR-2 - li /: BAR-3 - li /: '123' - li /: foobar123
OK
他にも例をば
[[ detail | midiの表 | [[ include | ex_tbl_1.txt ]] ]]
midiの表
分類
種別
データ長
内容 ヘッダ
ID
4バイト
"MThd" アスキー・コード 'M','T','h','d' の 4バイト サイズ
4バイト
以降のヘッダのバイト数をビッグエンディアンで格納
ヘッダの場合は値6固定なので、00,00,00,06 の4バイトフォーマットタイプ
2バイト
値0, 1, 2 のいづれかをビッグエンディアンで格納
ここではフォーマットタイプ 0 の SMF のみ扱うので、
00,00 の2バイトトラック数
2バイト
トラック数をビッグエンディアンで格納
フォーマットタイプが0の場合は、トラック数は1固定なので、
00,01 の2バイト時間分解能
2バイト
四分音符の分割数をビッグエンディアンで格納
四分音符1つをここで指定した値で分割した長さが、時間の最小単位
ただし1バイト目の最上位ビットが'1'の場合は、別の扱いとなる
ここでは1バイト目の最上位ビットが'0'のSMFのみを扱うトラック
ID
4バイト
"MTrk" アスキー・コード 'M','T','r','k' の 4バイト サイズ
4バイト
以降のトラックのバイト数をビッグエンディアンで格納 デルタタイム
可変長
イベント
可変長
デルタタイム
可変長
イベント
可変長
: デルタタイム
可変長
イベント
可変長
な表の例をinclude。
macro 分類: Type 種別: Kind データ長: Length of data 内容: Contents ヘッダ: Header トラック: Track サイズ: size フォーマットタイプ: Format Type Track数: Number of Tracks 時間分解能: Time Division デルタタイム: Delta Time イベント: Event バイト: ' Bytes' 可変長: variable length
などと変換の設定をしてみます。
[[ detail | midiの表 | [[ include | ex_tbl_1.txt ]] ]]
先ほどと同様にincludeしてみると
midiの表
Type
Kind
Length of data
Contents Header
ID
4 Bytes
"MThd" アスキー・コード 'M','T','h','d' の 4 Bytes size
4 Bytes
以降のHeaderの Bytes数をビッグエンディアンで格納
Headerの場合は値6固定なので、00,00,00,06 の4 BytesFormat Type
2 Bytes
値0, 1, 2 のいづれかをビッグエンディアンで格納
ここではFormat Type 0 の SMF のみ扱うので、
00,00 の2 BytesNumber of Tracks
2 Bytes
Number of Tracksをビッグエンディアンで格納
Format Typeが0の場合は、Number of Tracksは1固定なので、
00,01 の2 BytesTime Division
2 Bytes
四分音符の分割数をビッグエンディアンで格納
四分音符1つをここで指定した値で分割した長さが、時間の最小単位
ただし1 Bytes目の最上位ビットが'1'の場合は、別の扱いとなる
ここでは1 Bytes目の最上位ビットが'0'のSMFのみを扱うTrack
ID
4 Bytes
"MTrk" アスキー・コード 'M','T','r','k' の 4 Bytes size
4 Bytes
以降のTrackの Bytes数をビッグエンディアンで格納 Delta Time
variable length
Event
variable length
Delta Time
variable length
Event
variable length
: Delta Time
variable length
Event
variable length
えせ英語バージョンのできあがり。
まず、ulのdetailによる折り畳みがあったとして
[[ detail | label | [[ mode |^\ ul \ abc \ FOO \ def \ $ ]] ]]
label
この1行のFOOの箇所を、複数の行に変換したい場合。
複数行なので文字列のリスト。
macro FOO: - [[foo | bar ]] - ' foo-1' - ' foo-2' - hoge
なんですが、このように定義すると、意図した通りになりません。
$ cat bar_32.txt macro FOO: - [[foo | bar ]] - ' foo-1' - ' foo-2' - hoge p [[ detail | label | [[ mode | ^\ ul \ abc \ FOO \ def \ $ ]] ]] $ ./ezmd.py < bar_32.txt Traceback (most recent call last): File "./ezmd.py", line 762, in <module> lst = s_to_tag_lst(s) File "./ezmd.py", line 754, in s_to_tag_lst lst = ezmd(lst) File "./ezmd.py", line 713, in ezmd e.run() File "./ezmd.py", line 138, in run func(e) File "./ezmd.py", line 710, in <lambda> func = lambda e: do_mode(e.mode, e.tmp, hd_names) File "./ezmd.py", line 631, in do_mode buf = lst_strip(buf) File "./ezmd.py", line 102, in <lambda> lst_strip = lambda lst: list( map( lambda s: s.strip(), lst ) ) File "./ezmd.py", line 102, in <lambda> lst_strip = lambda lst: list( map( lambda s: s.strip(), lst ) ) AttributeError: 'list' object has no attribute 'strip'
改行のエスケープによる行の結合は、 macroによる変換よりも先に行われます。
[[ detail | label | [[ mode | ^\ ul \ abc \ FOO \ def \ $ ]] ]]
の箇所は、先に
[[ detail | labal | [[ mode |^ul 改行abc 改行FOO 改行def 改行$ ]] ]]
という1行になります。
その後で、FOOの箇所が複数の文字列に変換されるので
'FOO' の箇所が文字列のリスト '[[foo | bar]]' ' foo-1' ' foo-2' 'hoge'
この場合、内部処理的には
[[ detail | labal | [[ mode |^ul 改行abc 改行FOO 改行def 改行$ ]] ]]
がまず
'[[ detail | labal | [[ mode |^ul 改行abc 改行' 'FOO' ' 改行def 改行$ ]] ]]'
の3本のリストに。
それから、FOOの箇所が
'[[foo | bar]]' ' foo-1' ' foo-2' 'hoge'
に変換されるので
'[[ detail | labal | [[ mode |^ul 改行abc 改行' '[[foo | bar]]' ' foo-1' ' foo-2' 'hoge' ' 改行def 改行$ ]] ]]'
結果、複数の文字列に。
そう。
「例の形式」が複数の文字列にまたがってしまってます。
「例の形式」は1本の文字列の中で、改行を含んでいてもOKですが、 1本の文字列におさまってないとダメです。
ややこしい。
この場合の正解は
$ cat hoge_32.txt macro FOO: | [[foo | bar]] foo-1 foo-2 hoge p [[ detail | label | [[ mode | ^\ ul \ abc \ FOO \ def \ $ ]] ]]
先のダメな場合との差分は
$ diff -u bar_32.txt hoge_32.txt --- bar_32.txt 2019-10-13 10:45:45.000000000 +0900 +++ hoge_32.txt 2019-10-13 10:35:55.000000000 +0900 @@ -1,10 +1,10 @@ macro - FOO: - - [[foo | bar ]] - - ' foo-1' - - ' foo-2' - - hoge - + FOO: | + [[foo | bar]] + foo-1 + foo-2 + hoge + p [[ detail | label | [[ mode | ^\ ul \
FOOの変換後の文字列は、YAML形式で改行を含む1本の文字列です。
'[[foo | bar]]改行 foo-1改行 foo-2改行hoge'
になります。
これで実行すると
$ ./ezmd.py < hoge_32.txt - p: - details: - summary: label - ul: - li /: abc - li /: a href="foo": bar - ul: - li /: foo-1 - li /: foo-2 - li /: hoge - li /: def
貼り付けると
label
hoge_32.txt を include しても
[[ include | hoge_32.txt ]]
label
同様です。
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
macroによる文字列の置換
目次を折り畳もうとしても、うまくいきませんでした。
例えば
$ cat foo_33.txt h1 foo1 index ---- [[ detail | label | [[ mode | ^\ index \ $ ]] ]] ---- h2 foo2 h3 foo3 h2 bar2 h3 bar3
そのまま実行すると
$ ./ezmd.py < foo_33.txt - h1: a name="c_1_0": foo1 - ul: - li /: a href="#c_1_0": foo1 - ul: - li /: a href="#c_2_1": foo2 - ul: - li /: a href="#c_3_2": foo3 - li /: a href="#c_2_3": bar2 - ul: - li /: a href="#c_3_4": bar3 - p: hr: / - p: - details: - summary: label - index: [] - p: hr: / - h2: a name="c_2_1": foo2 - h3: a name="c_3_2": foo3 - h2: a name="c_2_3": bar2 - h3: a name="c_3_4": bar3
折り畳まない前者の方の目次はOKですが、 折り畳む後者の detail の側が残念な結果に。
目次生成処理の箇所
def do_index(hd_names): : def f(buf): names = names_get(hd_names, slice_get(buf) ) func = lambda h_i, n, name, s: ' ' * h_i + '[[#{}|'.format(name) + s + ']]' buf = list( map( lambda vs: func(*vs), names ) ) outbuf.push_tmp() do_mode_ul(buf) return outbuf.pop_tmp() return flat_map( lambda tag: f(tag.v) if tag.name == 'index' else tag, outbuf.lst_get() )
ここで、最後の行の処理。
折り畳みのdetailタグの中に、タグを挿入する場所を示すindexタグが入っていても、 これでは探せません。
タグの値vに、さらに別のタグや、タグのリストを保持してる場合も、 深く探索するように変更してます。
v33.patch
diff -ur v32/ezmd.py v33/ezmd.py
--- v32/ezmd.py 2019-10-13 02:24:13.000000000 +0900
+++ v33/ezmd.py 2019-10-13 14:04:53.000000000 +0900
@@ -697,7 +697,16 @@
do_mode_ul(buf)
return outbuf.pop_tmp()
- return flat_map( lambda tag: f(tag.v) if tag.name == 'index' else tag, outbuf.lst_get() )
+ def f_o(o):
+ if is_lst(o):
+ return flat_map(f_o, o)
+ if is_tag(o):
+ if o.name == 'index':
+ return f( o.v )
+ o.v = f_o( o.v )
+ return o
+
+ return f_o( outbuf.lst_get() )
def ezmd(lst):
lst = ['p'] + lst
$ cat v33.patch | patch -p1
$ ./to_html.py head.yaml index-v32.txt ezmd | diff -u index-v32.html - $
OK
$ ./ezmd.py < foo_33.txt - h1: a name="c_1_0": foo1 - ul: - li /: a href="#c_1_0": foo1 - ul: - li /: a href="#c_2_1": foo2 - ul: - li /: a href="#c_3_2": foo3 - li /: a href="#c_2_3": bar2 - ul: - li /: a href="#c_3_4": bar3 - p: hr: / - p: - details: - summary: label - ul: - li /: a href="#c_1_0": foo1 - ul: - li /: a href="#c_2_1": foo2 - ul: - li /: a href="#c_3_2": foo3 - li /: a href="#c_2_3": bar2 - ul: - li /: a href="#c_3_4": bar3 - p: hr: / - h2: a name="c_2_1": foo2 - h3: a name="c_3_2": foo3 - h2: a name="c_2_3": bar2 - h3: a name="c_3_4": bar3
OK
では早速、このページの先頭の目次も
index 2
から
[[name|c_index]] [[ detail | 目次 | [[ mode | ^\ index \ 2 \ $ ]] ]]
に変更してみます。
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
macroによる文字列の置換
目次は折り畳めないものか
同じような記述で、少しづつ内容に追加があるような場合。
内容をmacro定義にしておいて、内容に追加があるたびにmacro定義の値に「追加分」を追加。
macro定義を以前と同様に表示すれば、自動的に内容に追加分が反映されていると。
こんなストーリーを実現したく、macro変換の辞書の更新処理に手を入れてみました。
従来の仕様は
macro YAML形式の辞書 (他のモード)
YAML形式の辞書を「更新用辞書」とすると、
変換用の辞書.update( 更新用辞書 )
で、変換用の辞書を更新し
変換辞書から「キーと値が同一のもの」は削除。
以上の従来の仕様に対して、「追加用の辞書」というものを追加します。
更新用辞書の内容に、キー__ADD__が存在すると、値に「追加用の辞書」が定義されているものとして、辞書の更新に使用します。
「追加用の辞書」には、「更新用辞書」に含まれているキーと同じキーを指定して、 更新用辞書の「値」に追加する分の「値」を定義しておきます。
例えば、
macro foo: bar p foo macro __ADD__: foo: hoge p foo
とした場合
になって欲しいなと。
v34.patch
diff -ur v33/ezmd.py v34/ezmd.py
--- v33/ezmd.py 2019-10-13 14:04:53.000000000 +0900
+++ v34/ezmd.py 2019-10-13 23:34:07.000000000 +0900
@@ -591,6 +591,29 @@
macro_dic = {}
+def macro_dic_update(buf):
+ targ = macro_dic
+ d = yaml.load( '\n'.join(buf) )
+ if type(d) != dict:
+ return
+
+ add_k = '__ADD__'
+ add_d = d.pop(add_k) if add_k in d else {}
+
+ cv = lambda o: list( map(cv, o) ) if is_lst(o) else str(o)
+ d = dict( map( lambda kv: list( map(cv, kv) ), d.items() ) )
+ targ.update(d)
+ d = dict( filter( lambda kv: kv[0] != kv[1], targ.items() ) )
+
+ for (k, v) in add_d.items():
+ if k in d:
+ dv = d.get(k)
+ v = dv + v if str(dv) and is_str(v) else to_str(dv) + to_str(v)
+ d[k] = v
+
+ targ.clear()
+ targ.update(d)
+
def do_macro(buf):
for (k, v) in macro_dic.items():
def f(s):
@@ -606,14 +629,7 @@
def do_mode(mode, buf, hd_names):
if mode == 'macro':
- d = yaml.load( '\n'.join(buf) )
- if type(d) == dict:
- cv = lambda o: list( map(cv, o) ) if is_lst(o) else str(o)
- d = dict( map( lambda kv: list( map(cv, kv) ), d.items() ) )
- macro_dic.update(d)
- d = dict( filter( lambda kv: kv[0] != kv[1], macro_dic.items() ) )
- macro_dic.clear()
- macro_dic.update(d)
+ macro_dic_update(buf)
return
if mode != 'pre':
buf = do_macro(buf)
$ cat v34.patch | patch -p1
$ ./to_html.py head.yaml index-v33.txt ezmd | diff -u index-v33.html - $
OK
まずは仕様の例を
$ ./ezmd.py <<EOL > macro > foo: bar > p > foo > > macro > __ADD__: > foo: hoge > p > foo > EOL - p: - bar - p: - barhoge
OK
少し凝って
$ cat foo_34.txt p [[ detail | label | [[ mode | ^\ ul \ abc \ FOO \ def \ $ ]] ]] macro FOO: "[[foo]]\nfoo-2\n foo-2-1\n foo-2-2" p [[ detail | label | [[ mode | ^\ ul \ abc \ FOO \ def \ $ ]] ]] macro __ADD__: FOO: "\nbar\n bar-2" p [[ detail | label | [[ mode | ^\ ul \ abc \ FOO \ def \ $ ]] ]]
FOOの内容は
FOO "[[foo]]\nfoo-2\n foo-2-1\n foo-2-2" "[[foo]]\nfoo-2\n foo-2-1\n foo-2-2\nbar\n bar-2"
と変更されるはず...
$ ./ezmd.py < foo_34.txt - p: - details: - summary: label - ul: - li /: abc - li /: FOO - li /: def - p: - details: - summary: label - ul: - li /: abc - li /: a href="foo": foo - li /: foo-2 - ul: - li /: foo-2-1 - li /: foo-2-2 - li /: def - p: - details: - summary: label - ul: - li /: abc - li /: a href="foo": foo - li /: foo-2 - ul: - li /: foo-2-1 - li /: foo-2-2 - li /: bar - ul: - li /: bar-2 - li /: def
それらしく動いてます。
[[ include | foo_34.txt ]]
としてincludeしてみると
label
label
label
OKです。
todoリストの「済」項目をmacro定義にしてみます。
(実はこれがしたかった)
macro TODO_DONE: | "[[-|h1, h2, h3, ...]]" "[[-|p]]" "[[-|pre]]" "[[-|ul, li]]" "[[-|a (href)]]" "[[-|hr]]" "[[-|img]]" "[[-|video]]" "[[-|s]]" "[[-|目次機能]]" "[[-|headタグのtitleを何とかする]]" "[[-|バグ修正と調整]]" "[[-|br]]" "[[-|dl]]" "[[-|table]]" "[[-|ulからtableへの変換]]" "[[-|tblのセルの中の文字列で、先頭に複数の空白を含めたい]]" "[[-|tbl_ulモードでthタグも]]" "[[-|a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい]]" "[[-|a (name)]]" "[[-|h1,h2,h3で後に空行あったらデフォルトのpモードに]]" "[[-|モード遷移のバグ修正]]" "[[-|プロパティを細かく指定出来るように]]" "[[-|打ち消し線以外にも文字列の装飾を]]" "[[-|折り畳み]]" "[[-|例の形式の入れ子]]" "[[-|例の形式で簡単なpタグやulタグを生成できないものか]]" "[[-|例の形式で改行を許せぬものか]]" "[[-|ulで改行が消える不具合]]" "[[-|他のテキストファイルをinclude的に取り込みたい]]" "[[-|macroによる文字列の置換]]" "[[-|目次は折り畳めないものか]]"
などと定義しておいて
p [[detail| todo | [[mode| ^\ ul \ TODO_DONE \ macroの値への追加 \ コメント対応 \ $ ]] ]]
を記述すれば
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
macroによる文字列の置換
目次は折り畳めないものか
このように。
そこから、今回新たに「済」になった項目 「macroの値への追加」 を追加してみます。
macro __ADD__: TODO_DONE: "\n[[-|「macroの値への追加」]]"
先頭の改行を忘れずに!
そして「済」に移動した項目は削除して、todoを表示。
[[detail| todo | [[mode| ^\ ul \ TODO_DONE \ コメント対応 \ $ ]] ]]
これで今回のtodoの完成です。
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
macroによる文字列の置換
目次は折り畳めないものか
「macroの値への追加」
Python2の環境で、 このページ自身のテキスト index.txt を変換しようとすると、 いつしかエラーが出るようになっていました。
修正します。
$ ./to_html.py head.yaml index-v34.txt ezmd Traceback (most recent call last): File "./ezmd.py", line 787, in <module> lst = s_to_tag_lst(s) File "./ezmd.py", line 779, in s_to_tag_lst lst = ezmd(lst) File "./ezmd.py", line 738, in ezmd e.run() File "./ezmd.py", line 132, in run func(e) File "./ezmd.py", line 735, in <lambda> func = lambda e: do_mode(e.mode, e.tmp, hd_names) File "./ezmd.py", line 632, in do_mode macro_dic_update(buf) File "./ezmd.py", line 604, in macro_dic_update d = dict( map( lambda kv: list( map(cv, kv) ), d.items() ) ) File "./ezmd.py", line 604, in <lambda> d = dict( map( lambda kv: list( map(cv, kv) ), d.items() ) ) File "./ezmd.py", line 603, in <lambda> cv = lambda o: list( map(cv, o) ) if is_lst(o) else str(o) UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4: ordinal not in range(128)
Python3では文字列はstr型、Python2ではstr型かunicode型。
Python3ではstr型のoをstr(o)で変換しようとするとoのままでOK。
Python2ではunicode型のoをstr(o)でstrに変換しよとしてエラー。
yaml.load()した結果の変換辞書の値側で、「123」や「True」などがあれば、intやboolの値になっています。
そういうケースに備えて、ここでstr(o)で文字列に変換しています。
nkfの中で吸収したいところですが、ezmd.pyでimport sixもしてるので、とりあえずezmd.py側で。
まず、is_str(o) について。
この関数の判定は、ezmd.py の内部データの世界だけのものなので、ゆるゆるです。
is_lst(o) による「リスト」でもなく、かつ、is_tag(o) による「タグ」でもなければ、真にしてます。
これを、より厳しく。
Python3ならtype(o)がstrか、Python2ならtype(o)がstrかunicodeか。
この条件を追加します。
そうした上で、エラー発生箇所の
str(o)
を
o if is_str(o) else str(o)
に置き換えておきます。
これで、Python2でoがuniocdeのときはstr(o)をしないはず。
v35.patch
diff -ur v34/ezmd.py v35/ezmd.py
--- v34/ezmd.py 2019-10-13 23:34:07.000000000 +0900
+++ v35/ezmd.py 2019-10-15 20:11:07.000000000 +0900
@@ -163,9 +163,11 @@
n = 1 if is_lst(o) else len(delim)
return ( o[:i], o[i+n:] )
+str_types = (str, unicode) if six.PY2 else (str,)
+
is_lst = lambda o: type(o) == list
is_tag = lambda o: isinstance(o, Empty) # !!!
-is_str = lambda o: not is_lst(o) and not is_tag(o)
+is_str = lambda o: not is_lst(o) and not is_tag(o) and type(o) in str_types
lst_strip_is_str = lambda lst: list( map( lambda o: o.strip() if is_str(o) else o, lst ) )
def delim_pop(o, delim):
@@ -600,7 +602,7 @@
add_k = '__ADD__'
add_d = d.pop(add_k) if add_k in d else {}
- cv = lambda o: list( map(cv, o) ) if is_lst(o) else str(o)
+ cv = lambda o: list( map(cv, o) ) if is_lst(o) else ( o if is_str(o) else str(o) )
d = dict( map( lambda kv: list( map(cv, kv) ), d.items() ) )
targ.update(d)
d = dict( filter( lambda kv: kv[0] != kv[1], targ.items() ) )
@@ -608,23 +610,31 @@
for (k, v) in add_d.items():
if k in d:
dv = d.get(k)
- v = dv + v if str(dv) and is_str(v) else to_str(dv) + to_str(v)
+ v = dv + v if is_str(dv) and is_str(v) else to_str(dv) + to_str(v)
d[k] = v
targ.clear()
targ.update(d)
def do_macro(buf):
- for (k, v) in macro_dic.items():
- def f(s):
- if k in s:
- if is_str(v):
- return s.replace(k, v)
- if is_lst(v):
- lst = list( map( lambda a: [a] if a else [], s.split(k) ) )
- return sum( map( lambda b: b+v, lst[:-1] ), [] ) + lst[-1]
- return s
- buf = flat_map(f, buf)
+ def f_dic(buf):
+ for (k, v) in macro_dic.items():
+ def f(s):
+ if k in s:
+ if is_str(v):
+ return s.replace(k, v)
+ if is_lst(v):
+ lst = list( map( lambda a: [a] if a else [], s.split(k) ) )
+ return sum( map( lambda b: b+v, lst[:-1] ), [] ) + lst[-1]
+ return s
+ buf = flat_map(f, buf)
+ return buf
+
+ for i in range(20):
+ bak = buf
+ buf = f_dic(buf)
+ if buf == bak:
+ break
return buf
def do_mode(mode, buf, hd_names):
@@ -769,7 +779,7 @@
if is_lst(o):
return list( map(rm_nl_tag, o) )
# o is tag
- if o.name != 'pre':
+ if o.name not in ('pre', 'yaml') :
o.v = rm_nl_tag(o.v)
return o
$ cat v35.patch | patch -p1
エラー問題の他にも、ポカをみつけたので修正を入れてます。
$ ./to_html.py head.yaml index-v34.txt ezmd | diff -u index-v34.html - $
そしてPython2の環境にて
$ ./to_html.py head.yaml index-v34.txt ezmd | diff -u index-v34.html - | nkf -u | grep ^[-+] : -<table border="1" cellspacing="0"><tr><td>foo</td> +<table cellspacing="0" border="1"><tr><td>foo</td> -<table border="1" cellspacing="0"><tr><td>foo</td> +<table cellspacing="0" border="1"><tr><td>foo</td> : -<table border="1" cellspacing="0"><tr><th>分類</th> +<table cellspacing="0" border="1"><tr><th>分類</th> -<tr><td align="center" colspan="4">:</td></tr> +<tr><td colspan="4" align="center">:</td></tr> -<table border="1" cellspacing="0"><tr><th>Type</th> +<table cellspacing="0" border="1"><tr><th>Type</th> -<tr><td align="center" colspan="4">:</td></tr> +<tr><td colspan="4" align="center">:</td></tr>
OK エラーは消え、結果にタグの属性の順番の違い以外の変化はありません。
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
macroによる文字列の置換
目次は折り畳めないものか
「macroの値への追加」
Python2の環境でエラー
ちょっとテキスト中の一部を「無効化」して様子を見てから、 また復活させたいてな事が多々あります。
テキストを処理するときに、コメントとして扱う対応を入れます。
YAML形式と同様に「'#'以降行末まで」にしたいところですが、
[[name|foo]] [[#foo|bar hoge]]
的に、ちょいちょい重要な'#'が出てくるので、パースして判断するのが繁雑です。
ここはひとつ、「行頭が'#'で始まる行はコメント」で。
v36.patch
diff -ur v35/ezmd.py v36/ezmd.py
--- v35/ezmd.py 2019-10-15 20:11:07.000000000 +0900
+++ v36/ezmd.py 2019-10-15 20:40:16.000000000 +0900
@@ -750,6 +750,9 @@
res = do_index(hd_names)
return res
+def cut_comment(buf):
+ return list( filter( lambda s: not s.startswith('#'), buf ) )
+
def pre_split_esc_join(s, delim):
buf = s.split(delim)
@@ -759,7 +762,7 @@
e = buf_loop_new(buf, is_call, func)
e.run()
- f = lambda buf: buf if buf and buf[0] == 'pre' else esc_join(buf, delim)
+ f = lambda buf: buf if buf and buf[0] == 'pre' else esc_join( cut_comment(buf), delim)
return sum( map(f, lst), [] )
def yaml_dump(o):
$ cat v36.patch | patch -p1
It's very simple.
preタグ以外について、 行末エスケープによる「行の結合」処理の直前に、 コメント処理を入れてみました。
聖域preタグの中は、行頭が'#'でも有効です。
行結合前にコメントを処理するので
p foo \ bar \ hoge
を
p foo \ # bar \ hoge
にすると
p foo \ hoge
相当になります。
$ ./to_html.py head.yaml index-v35.txt ezmd | diff -u index-v35.html - $
OK
$ ./ezmd.py <<EOL > ul > foo > bar > hoge > EOL - ul: - li /: foo - li /: bar - li /: hoge $ ./ezmd.py <<EOL > ul > foo > # bar > hoge > EOL - ul: - li /: foo - li /: hoge $ ./ezmd.py <<EOL > p > foo \\ > bar \\ > hoge > EOL - p: - foobarhoge $ ./ezmd.py <<EOL > p > foo \\ > # bar \\ > hoge > EOL - p: - foohoge
OK
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
macroによる文字列の置換
目次は折り畳めないものか
「macroの値への追加」
Python2の環境でエラー
コメント対応
macroによる変換は、do_mode()関数冒頭で、 モードの処理をする直前の箇所に入ってます。
ここで、聖域「preモード」以外を判別して、 モード処理対象の文字列リストに変換をかけてます。
なので、do_mode()呼び出しで指定された引数「mode」の中だけの、 文字列の変換になります。
例えば
$ cat foo_37.txt macro foo: hoge bar: - ul - hoge-1 - hoge-2 p foo bar
などと記述しても
$ ./ezmd.py < foo_37.txt - p: - hoge - p: - ul - hoge-1 - hoge-2
となります。
barの箇所は、pモードから逃れる事はできません。
そこを何とか
p foo bar
の箇所は
p hoge ul hoge-1 hoge-2
の扱いにしたいところ。
対応してみます。
v37.patch
diff -ur v36/ezmd.py v37/ezmd.py
--- v36/ezmd.py 2019-10-15 20:40:16.000000000 +0900
+++ v37/ezmd.py 2019-10-15 20:51:00.000000000 +0900
@@ -124,10 +124,12 @@
def buf_loop_new(buf, is_call, func):
e = Empty()
e.mode = e.next_mode = None
+ e.buf = buf
e.tmp = []
def run():
- for e.s in buf:
+ while e.buf:
+ e.s = e.buf.pop(0)
if is_call(e):
func(e)
e.tmp = []
@@ -640,9 +642,7 @@
def do_mode(mode, buf, hd_names):
if mode == 'macro':
macro_dic_update(buf)
- return
- if mode != 'pre':
- buf = do_macro(buf)
+ return
if mode in heads:
buf = lst_strip(buf)
@@ -739,6 +739,9 @@
(buf, hd_names) = ( [], [] )
def is_call(e):
+ if e.mode not in ('pre', 'macro'):
+ r = do_macro( [e.s] )
+ (e.s, e.buf) = ( r[0], r[1:] + e.buf )
next_mode_switch(e)
return e.next_mode != e.mode
$ cat v37.patch | patch -p1
macro変換の位置を、do_mode()関数の冒頭から、 ezmd()関数内で do_mode() を呼び出すよりも前にしました。
実際には buf_loop_new()関数からコールバック的に呼び出される、 is_call()関数の中で変換してます。
buf_loop_new()関数の中での buf の扱い方にも修正を入れました。
$ ./to_html.py head.yaml index-v36.txt ezmd | diff -u index-v36.html - $
OK
$ ./ezmd.py < foo_37.txt - p: - hoge - ul: - li /: hoge-1 - li /: hoge-2
OK
では早速、TODO_SHOWなるマクロを定義して使ってみます。
macro TODO_YET: macroに引数を TODO_SHOW: | [[ detail | todo | [[ mode | ^\ ul \ TODO_DONE \ TODO_YET \ $ ]] ]] __ADD__: TODO_DONE: "\n[[-| macroの変換結果に「例の形式」やモードの記述を含めたい ]]" p TODO_SHOW
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
macroによる文字列の置換
目次は折り畳めないものか
「macroの値への追加」
Python2の環境でエラー
コメント対応
macroの変換結果に「例の形式」やモードの記述を含めたい
マクロに引数の変換を追加してみます。
変換辞書に
を追加します。
「引数の辞書は」
として用意します。
例えば変換辞書が
FOO: hello NAME, you should DO __ARG__: FOO: [NAME, DO]
という状態のときに
FOO(bar, work)
が現れると
hello bar, you should work
に変換。
FOO(hoge, sleep)
だと
hello hoge, you should sleep
てな具合に。
そして「変換辞書」を、そのような状態に設定するために、 macroモード中に記述する「更新用の辞書」はどうすべきか?
やはり __ARG__ というキーを使って記述します。
macro FOO: hello NAME, you should DO __ARG__: FOO: [NAME, DO]
仮引数の設定を削除するときは、値に [] の空リストを指定します。
macro __ARG__: FOO: []
また、変換用辞書からキーが削除されたら、__ARG__ 側の設定も削除されます。
マクロ呼び出しでは、キーの後に
( xxx, xxx, ... )
括弧の中に、','で区切って実引数を並べて指定します。
仮引数と実引数の個数が合わないときは、 合う分までだけ使って変換をかけます。
なので、実引数が足りない場合は、一部は仮引数のままで表示されます。
v38.patch
diff -ur v37/ezmd.py v38/ezmd.py
--- v37/ezmd.py 2019-10-15 20:51:00.000000000 +0900
+++ v38/ezmd.py 2019-10-16 23:04:00.000000000 +0900
@@ -601,8 +601,8 @@
if type(d) != dict:
return
- add_k = '__ADD__'
- add_d = d.pop(add_k) if add_k in d else {}
+ ks = (add_k, arg_k) = ('__ADD__', '__ARG__')
+ (add_d, arg_d) = map( lambda k: d.pop(k) if k in d else {}, ks )
cv = lambda o: list( map(cv, o) ) if is_lst(o) else ( o if is_str(o) else str(o) )
d = dict( map( lambda kv: list( map(cv, kv) ), d.items() ) )
@@ -615,20 +615,60 @@
v = dv + v if is_str(dv) and is_str(v) else to_str(dv) + to_str(v)
d[k] = v
+ ta = targ.get(arg_k, {})
targ.clear()
targ.update(d)
+ if arg_d:
+ ta.update(arg_d)
+ ta = dict( filter( lambda kv: kv[0] in targ and kv[1], ta.items() ) )
+ if ta:
+ targ[arg_k] = ta
+
def do_macro(buf):
+ def alst_get(s):
+ s = s[1:] # skip '('
+ lst = []
+ while s and ')' in s:
+ delim = ',' if ',' in s and s_idx(s, ',') < s_idx(s, ')') else ')'
+ (h, s) = div_delim(s, delim)
+ lst.append( h.strip() )
+ return (lst, s)
+
+ def do_arg(s, k, v, arg_d):
+ if k not in arg_d:
+ return (s, v)
+
+ arg_lst = arg_d.get(k, [])
+ (h, t) = div_delim(s, k)
+ t = strip_head(t)
+ if not t or t[0] != '(':
+ return (s, v)
+
+ (lst, t) = alst_get(t)
+ for (src, dst) in zip(arg_lst, lst):
+ f = lambda v: list( map(f, v) ) if is_lst(v) else v.replace(src, dst) if src in v else v
+ v = f(v)
+ s = h + k + t
+ return (s, v)
+
def f_dic(buf):
- for (k, v) in macro_dic.items():
+ arg_k = '__ARG__'
+ arg_d = macro_dic.get(arg_k, {})
+ kvs = list( filter( lambda kv: kv[0] != arg_k, macro_dic.items() ) )
+ for (k, v_) in kvs:
def f(s):
- if k in s:
- if is_str(v):
- return s.replace(k, v)
- if is_lst(v):
- lst = list( map( lambda a: [a] if a else [], s.split(k) ) )
- return sum( map( lambda b: b+v, lst[:-1] ), [] ) + lst[-1]
- return s
+ if k not in s:
+ return s
+ r = [] if is_lst(v_) else ''
+ while k in s:
+ (s, v) = do_arg(s, k, v_, arg_d)
+ (h, s) = div_delim(s, k)
+ r += h if is_str(v_) else [h]
+ r += v
+ if s:
+ r += s if is_str(v_) else [s]
+ return r
buf = flat_map(f, buf)
return buf
$ cat v38.patch | patch -p1
$ ./to_html.py head.yaml index-v37.txt ezmd | diff -u index-v37.html - $
OK
macro foo: hoge bar: - ul - hoge-1 - fuga-2 __ARG__: bar: [hoge, fuga] p foo bar(x, y) p foo bar # 削除用 macro foo: foo bar: bar p foo bar(x, y)
の場合
hoge
hoge
foo
bar(x, y)
OK
さほど変わらない気もしますが、例えば次のパターン
[[ detail | label | [[ mode | ^\ ul \ foo \ bar \ $ ]] ]]
label
このパターンを引数付きのマクロにしてみます。
macro DETAIL_MODE: | [[ detail | label | [[ mode | ^\ modes \ $ ]] ]] __ARG__: DETAIL_MODE: [ label, modes ]
などと定義しておいて
DETAIL_MODE(foo_tbl, \ tbl \ tbl_ul \ foo \ bar \ hoge \ )
などとマクロを使ってみると
foo_tbl
foo bar
hoge
このように。
一応、中間のYAML形式も確認しておきます。
$ cat foo_38.txt macro DETAIL_MODE: | [[ detail | label | [[ mode | ^\ modes \ $ ]] ]] __ARG__: DETAIL_MODE: [ label, modes ] p DETAIL_MODE(foo_tbl, \ tbl \ tbl_ul \ foo \ bar \ hoge \ )
$ ./ezmd.py < foo_38.txt - p: - details: - summary: foo_tbl - table cellspacing="0" border="1": - tr: - td colspan="2": foo - tr: - td: bar - td: hoge
どちらかと言うと、展開後のテキストを表示したいところでしたね。
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
macroによる文字列の置換
目次は折り畳めないものか
「macroの値への追加」
Python2の環境でエラー
コメント対応
macroの変換結果に「例の形式」やモードの記述を含めたい
macroに引数を
コマンド引数のオプションを追加します。
って、ここまでオプション指定は皆無でした。
import sys
からの追加です。
gccの仕様にならって -E で。
$ gcc --help | grep -i preprocess | grep -i only -E Preprocess only; do not compile, assemble or link
としてみます。
v39.patch
diff -ur v38/ezmd.py v39/ezmd.py
--- v38/ezmd.py 2019-10-16 23:04:00.000000000 +0900
+++ v39/ezmd.py 2019-10-17 00:17:00.000000000 +0900
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+import sys
import subprocess
import yaml
import six
@@ -594,6 +595,7 @@
outbuf.append( tbls_join( outbuf.pop_tmp() ) )
macro_dic = {}
+macro_exp = []
def macro_dic_update(buf):
targ = macro_dic
@@ -782,6 +784,7 @@
if e.mode not in ('pre', 'macro'):
r = do_macro( [e.s] )
(e.s, e.buf) = ( r[0], r[1:] + e.buf )
+ macro_exp.append(e.s)
next_mode_switch(e)
return e.next_mode != e.mode
@@ -844,6 +847,9 @@
lst = flat_map( tag_to_dic, lst )
u8 = yaml_dump(lst)
+ if '-E' in sys.argv:
+ s = '\n'.join(macro_exp)
+ u8 = nkf.str_to(s, '-u')
b = nkf.cvt(u8, nkf_opt) if nkf_opt != '-u' else u8
nkf.put_stdout(b)
# EOF
$ cat v39.patch | patch -p1
$ ./to_html.py head.yaml index-v38.txt ezmd | diff -u index-v38.html - $
OK
前回の foo_38.txt を使って
$ cat foo_38.txt macro DETAIL_MODE: | [[ detail | label | [[ mode | ^\ modes \ $ ]] ]] __ARG__: DETAIL_MODE: [ label, modes ] p DETAIL_MODE(foo_tbl, \ tbl \ tbl_ul \ foo \ bar \ hoge \ )
$ ./ezmd.py -E < foo_38.txt p macro DETAIL_MODE: | [[ detail | label | [[ mode | ^ modes $ ]] ]] __ARG__: DETAIL_MODE: [ label, modes ] p [[ detail | foo_tbl | [[ mode | ^ tbl tbl_ul foo bar hoge $ ]] ]] p tbl tbl_ul foo bar hoge
$ ./ezmd.py -E < foo_38.txt | diff -u foo_38.txt - --- foo_38.txt 2019-10-16 19:33:29.624169000 +0900 +++ - 2019-10-17 00:35:29.695229535 +0900 @@ -1,16 +1,26 @@ +p macro DETAIL_MODE: | - [[ detail | label | [[ mode | ^\ - modes \ + [[ detail | label | [[ mode | ^ + modes $ ]] ]] __ARG__: DETAIL_MODE: [ label, modes ] p -DETAIL_MODE(foo_tbl, \ -tbl \ -tbl_ul \ - foo \ - bar \ - hoge \ -) +[[ detail | foo_tbl | [[ mode | ^ +tbl +tbl_ul + foo + bar + hoge +$ ]] ]] + + +p + +tbl +tbl_ul + foo + bar + hoge
「何となく展開された内容」になってます。
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
macroによる文字列の置換
目次は折り畳めないものか
「macroの値への追加」
Python2の環境でエラー
コメント対応
macroの変換結果に「例の形式」やモードの記述を含めたい
macroに引数を
マクロの展開を確認し易いように
場当たり的に改良してみました。
v40.patch
diff -ur v39/ezmd.py v40/ezmd.py
--- v39/ezmd.py 2019-10-17 00:17:00.000000000 +0900
+++ v40/ezmd.py 2019-10-17 01:03:00.000000000 +0900
@@ -784,7 +784,10 @@
if e.mode not in ('pre', 'macro'):
r = do_macro( [e.s] )
(e.s, e.buf) = ( r[0], r[1:] + e.buf )
- macro_exp.append(e.s)
+
+ if outbuf.name == 'org':
+ macro_exp.append( e.s.replace('\n', '\\\n') )
+
next_mode_switch(e)
return e.next_mode != e.mode
$ cat v40.patch | patch -p1
出力先のoutbufの切替えが、「テンポラリ」バッファじゃなく、 「オリジナル」バッファのときだけ、展開結果を表示します。
展開結果の文字列に「改行」が含まれていると、 行結合処理を逆にさかのぼらせて、「エスケープ」+「改行」 に置き換えなおして表示します。
関係ないはずですが、一応...
$ ./to_html.py head.yaml index-v39.txt ezmd | diff -u index-v39.html - $
OK
前回同様に foo_38.txt を使って
$ cat foo_38.txt macro DETAIL_MODE: | [[ detail | label | [[ mode | ^\ modes \ $ ]] ]] __ARG__: DETAIL_MODE: [ label, modes ] p DETAIL_MODE(foo_tbl, \ tbl \ tbl_ul \ foo \ bar \ hoge \ )
$ ./ezmd.py -E < foo_38.txt p macro DETAIL_MODE: | [[ detail | label | [[ mode | ^\ modes \ $ ]] ]] __ARG__: DETAIL_MODE: [ label, modes ] p [[ detail | foo_tbl | [[ mode | ^\ tbl \ tbl_ul \ foo \ bar \ hoge \ $ ]] ]]\
$ ./ezmd.py -E < foo_38.txt | diff -u foo_38.txt - --- foo_38.txt 2019-10-16 19:33:29.624169000 +0900 +++ - 2019-10-17 01:18:32.628846240 +0900 @@ -1,3 +1,4 @@ +p macro DETAIL_MODE: | [[ detail | label | [[ mode | ^\ @@ -7,10 +8,11 @@ DETAIL_MODE: [ label, modes ] p -DETAIL_MODE(foo_tbl, \ +[[ detail | foo_tbl | [[ mode | ^\ tbl \ tbl_ul \ foo \ bar \ hoge \ -) +$ ]] ]]\ +
それらしくなりました。
先頭の p は、ezmd()関数の冒頭で、 デフォルトpモードとして最初に追加してた分になります。
def ezmd(lst): lst = ['p'] + lst (buf, hd_names) = ( [], [] ) :
-E 出力結果を、ちゃんと処理できるだろうか?
まず
$ ./ezmd.py < foo_38.txt | tee foo_38.yaml - p: - details: - summary: foo_tbl - table cellspacing="0" border="1": - tr: - td colspan="2": foo - tr: - td: bar - td: hoge
そして
$ ./ezmd.py -E < foo_38.txt | ./ezmd.py - p: - details: - summary: foo_tbl - table cellspacing="0" border="1": - tr: - td colspan="2": foo - tr: - td: bar - td: hoge
$ ./ezmd.py -E < foo_38.txt | ./ezmd.py | diff -u foo_38.yaml - $
とりあえず一致。
この短いテキストでの例だけでは「なんとも」ですが...
とりあえずincludeは展開されないはず。
はっ。出力先が「オリジナル」バッファのときだけに限定したので、 swbufモードで切替えた時も、表示されない...
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
macroによる文字列の置換
目次は折り畳めないものか
「macroの値への追加」
Python2の環境でエラー
コメント対応
macroの変換結果に「例の形式」やモードの記述を含めたい
macroに引数を
マクロの展開を確認し易いように
マクロの展開表示をもうちょっと改良すべし
マクロ展開結果を記録するかどうかを、
「出力バッファの状態」
で判定するのではなく、
「例の形式」によるモード処理中なのかどうか
で判定するようにしてみました。
v41.patch
diff -ur v40/ezmd.py v41/ezmd.py
--- v40/ezmd.py 2019-10-17 01:03:00.000000000 +0900
+++ v41/ezmd.py 2019-10-17 06:07:00.000000000 +0900
@@ -776,7 +776,7 @@
return f_o( outbuf.lst_get() )
-def ezmd(lst):
+def ezmd(lst, rec_exp=False):
lst = ['p'] + lst
(buf, hd_names) = ( [], [] )
@@ -785,7 +785,7 @@
r = do_macro( [e.s] )
(e.s, e.buf) = ( r[0], r[1:] + e.buf )
- if outbuf.name == 'org':
+ if rec_exp:
macro_exp.append( e.s.replace('\n', '\\\n') )
next_mode_switch(e)
@@ -835,22 +835,24 @@
o.v = rm_nl_tag(o.v)
return o
-def s_to_tag_lst(s):
+def s_to_tag_lst(s, rec_exp=False):
lst = pre_split_esc_join(s, '\n')
lst = list( map( strip_tail, lst ) )
- lst = ezmd(lst)
+ lst = ezmd(lst, rec_exp)
lst = list( map( rm_nl_tag, lst) )
return lst
if __name__ == "__main__":
+ opt_E = '-E' in sys.argv
+
b = nkf.get_stdin()
(s, nkf_opt) = nkf.to_str(b)
- lst = s_to_tag_lst(s)
+ lst = s_to_tag_lst(s, opt_E)
lst = flat_map( tag_to_dic, lst )
u8 = yaml_dump(lst)
- if '-E' in sys.argv:
+ if opt_E:
s = '\n'.join(macro_exp)
u8 = nkf.str_to(s, '-u')
b = nkf.cvt(u8, nkf_opt) if nkf_opt != '-u' else u8
$ cat v41.patch | patch -p1
関係ないはずですが、一応...
$ ./to_html.py head.yaml index-v40.txt ezmd | diff -u index-v40.html - $
OK
まずは前回同様に foo_38.txt を使って
$ cat foo_38.txt macro DETAIL_MODE: | [[ detail | label | [[ mode | ^\ modes \ $ ]] ]] __ARG__: DETAIL_MODE: [ label, modes ] p DETAIL_MODE(foo_tbl, \ tbl \ tbl_ul \ foo \ bar \ hoge \ )
$ ./ezmd.py -E < foo_38.txt | diff -u foo_38.txt - --- foo_38.txt 2019-10-16 19:33:29.624169000 +0900 +++ - 2019-10-17 06:11:28.313139204 +0900 @@ -1,3 +1,4 @@ +p macro DETAIL_MODE: | [[ detail | label | [[ mode | ^\ @@ -7,10 +8,11 @@ DETAIL_MODE: [ label, modes ] p -DETAIL_MODE(foo_tbl, \ +[[ detail | foo_tbl | [[ mode | ^\ tbl \ tbl_ul \ foo \ bar \ hoge \ -) +$ ]] ]]\ +
$ ./ezmd.py < foo_38.txt | tee foo_38.yaml - p: - details: - summary: foo_tbl - table cellspacing="0" border="1": - tr: - td colspan="2": foo - tr: - td: bar - td: hoge
$ ./ezmd.py -E < foo_38.txt | ./ezmd.py | diff -u foo_38.yaml - $
ではひとつ、大きなテキストで。
$ ./ezmd.py -E < index-v40.txt | diff -u index-v40.txt - | nkf -u | less --- index-v40.txt 2019-10-17 01:33:49.632704000 +0900 +++ - 2019-10-17 06:46:55.271461558 +0900 @@ -1,3 +1,4 @@ +p h1 簡易なおれおれマークダウン 2019秋 @@ -8323,7 +8324,11 @@ [[ detail | label | [[ mode | ^\ ul \ abc \ -FOO \ +[[foo | bar]]\ + foo-1\ + foo-2\ +hoge\ + \ def \ $ ]] ]] @@ -8904,7 +8909,39 @@ [[detail| todo | [[mode| ^\ ul \ -TODO_DONE \ +"[[-|h1, h2, h3, ...]]"\ +"[[-|p]]"\ +"[[-|pre]]"\ :
確かにマクロ展開分だけの変化に見えます。
$ ./ezmd.py < index-v40.txt > index-v40.yaml $ nkf -u index-v40.yaml | head - h1: a name="c_1_0": 簡易なおれおれマークダウン 2019秋 - p: - a name="c_index": '' - p: - details: - summary: 目次 - ul: - li /: a href="#c_2_1": はじめに
YAML形式にしておいて
$ ./ezmd.py -E < index-v40.txt | ./ezmd.py | diff -u index-v40.yaml - $
完全に一致。OK
$ cat index-v40.txt | wc -l 9962 $ ./ezmd.py -E < index-v40.txt | diff -u index-v40.txt - | wc -l 510 $ ./ezmd.py -E < index-v40.txt | ./ezmd.py | wc -l 11021
1万行程度の入力テキスト中、 510行程度の差分があって、 1万行程度のYAML形式の出力が一致してます。
おそらく「うまくいってる」はずです。
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
macroによる文字列の置換
目次は折り畳めないものか
「macroの値への追加」
Python2の環境でエラー
コメント対応
macroの変換結果に「例の形式」やモードの記述を含めたい
macroに引数を
マクロの展開を確認し易いように
マクロの展開表示をもうちょっと改良すべし
マクロ展開表示の改良その2
既存のテキストにモード行を入れる作業をしてみると、 pモードからulモードへ、そして再びpモードに戻るようなパターンが多々ありました。
ulモードでもpreモードのように、終端で'/'が使えても良いかなぁと。
どうせなら、ul以外の他のモードでも使えて良いかなぁと。
さらにどうせなら、スタック構造とまではせずとも、1つ前のモードを覚えておいて、 '/'行で1つ前のモードに戻れたら良いかなぁと。
互換性のため、既存のpreモードの'/'は従来通りの動作を保ちます。
基本的にその他のモードでは、'/'だけの行が現れると、
1つ前のモードに遷移します。
(前の状態に戻るわけではなく、前のモードで新たに開始します)
v42.patch
diff -ur v41/ezmd.py v42/ezmd.py
--- v41/ezmd.py 2019-10-17 06:07:00.000000000 +0900
+++ v42/ezmd.py 2019-10-29 19:54:29.000000000 +0900
@@ -18,6 +18,8 @@
(e.s, e.next_mode) = (None, 'p')
elif e.mode in heads and not e.s.strip():
(e.s, e.next_mode) = (None, 'p' if e.tmp else e.mode)
+ elif e.s == '/':
+ (e.s, e.next_mode) = (None, e.bak_mode)
elif e.s in modes:
(e.s, e.next_mode) = (None, e.s)
elif is_all_ge_n(e.s, '-', 4):
@@ -124,7 +126,7 @@
def buf_loop_new(buf, is_call, func):
e = Empty()
- e.mode = e.next_mode = None
+ e.mode = e.next_mode = e.bak_mode = None
e.buf = buf
e.tmp = []
@@ -134,7 +136,7 @@
if is_call(e):
func(e)
e.tmp = []
- e.mode = e.next_mode
+ (e.mode, e.bak_mode) = (e.next_mode, e.mode)
if e.s != None:
e.tmp.append(e.s)
$ cat v42.patch | patch -p1
短いです。
$ ./to_html.py head.yaml index-v41.txt ezmd | diff -u index-v41.html - $
OK
例えば
h4 sample v42 foo bar ul 大阪 京都 / hoge fuga tbl tbl_ul 滋賀 奈良 / hello world / 名古屋 東京 / xxx yyy
の場合は
foo bar
hoge fuga
滋賀 |
奈良 |
hello world
名古屋 |
東京 |
xxx yyy
todo
h1, h2, h3, ...
p
pre
ul, li
a (href)
hr
img
video
s
目次機能
headタグのtitleを何とかする
バグ修正と調整
br
dl
table
ulからtableへの変換
tblのセルの中の文字列で、先頭に複数の空白を含めたい
tbl_ulモードでthタグも
a (href)タグで文字列に'|'を含めるとダメなのを何とかしたい
a (name)
h1,h2,h3で後に空行あったらデフォルトのpモードに
モード遷移のバグ修正
プロパティを細かく指定出来るように
打ち消し線以外にも文字列の装飾を
折り畳み
例の形式の入れ子
例の形式で簡単なpタグやulタグを生成できないものか
例の形式で改行を許せぬものか
ulで改行が消える不具合
他のテキストファイルをinclude的に取り込みたい
macroによる文字列の置換
目次は折り畳めないものか
「macroの値への追加」
Python2の環境でエラー
コメント対応
macroの変換結果に「例の形式」やモードの記述を含めたい
macroに引数を
マクロの展開を確認し易いように
マクロの展開表示をもうちょっと改良すべし
マクロ展開表示の改良その2
pre以外でも'/'を使えるように
永らく放置されてた不具合がありました。
headタグが2重に出力されておりました。
修正します。
あと、.py群を1つ下のディレクトリ、例えばdoc_base/に移動しておいて、 そこにcdしてから実行するような場合、 includeではcdした事がわからず、ファイルが見つからない不具合がありました。
場当たり的ですが、includeしたいファイルが無いと、 とりあえず1つ上のディレクトリで試すようにしてみました。
v43.patch
diff -ur v42/ezmd.py v43/ezmd.py
--- v42/ezmd.py Tue Oct 29 19:54:29 2019
+++ v43/ezmd.py Fri Jan 24 12:06:55 2020
@@ -1,6 +1,7 @@
#!/usr/bin/env python
import sys
+import os
import subprocess
import yaml
import six
@@ -213,6 +214,10 @@
def text_get(s):
ps = ('http', 'https')
cmd = 'wget -q -O-' if any( map( lambda p: s.startswith(p + '://'), ps ) ) else 'cat'
+
+ if cmd == 'cat' and not os.path.exists(s): # todo
+ s = '../' + s
+
b = subprocess.check_output( cmd + ' ' + s, shell=True )
(s, nkf_opt) = nkf.to_str(b)
return s
diff -ur v42/to_html.py v43/to_html.py
--- v42/to_html.py Fri Sep 27 22:15:57 2019
+++ v43/to_html.py Fri Jan 24 11:42:20 2020
@@ -14,7 +14,7 @@
cmd_title = "sed 's/^- title: .*/- title: {}/'".format(title) if title else 'cat'
cmd_hd = 'cat {} | {} | ./ezhtml.py y'.format( sys.argv[1], cmd_title )
- cmd = "( echo '<html><head>' ; {} ; echo '</head><body>' ; ./ezmd.py < {} | ./ezhtml.py y ; echo '</body></html>' ) | nkf -j";
+ cmd = "( echo '<html>' ; {} ; echo '<body>' ; ./ezmd.py < {} | ./ezhtml.py y ; echo '</body></html>' ) | nkf -j";
cmd = cmd.format( cmd_hd, sys.argv[2] )
#print(cmd)
subprocess.call(cmd, shell=True)
$ cat v43.patch | patch -p1
pythonのユーティリティ・プログラム 2020冬 が揃ってきたので、to_html.pyの見直しもかねて、kon_utを使うようにしてみました。
v44.patch
diff -urN v43/head.yaml v44/head.yaml
--- v43/head.yaml 2019-10-15 17:21:09.000000000 +0900
+++ v44/head.yaml 2020-01-30 23:02:36.000000000 +0900
@@ -1,19 +1,6 @@
-head:
-- ''
-- '!--': ' Global site tag (gtag.js) - Google Analytics '
-- 'script async src="https://www.googletagmanager.com/gtag/js?id=UA-137368912-1"': ''
-- script:
- - ''
- - " window.dataLayer = window.dataLayer || [];"
- - " function gtag(){dataLayer.push(arguments);}"
- - " gtag('js', new Date());"
- - ''
- - " gtag('config', 'UA-137368912-1');"
- - ''
-- ''
- meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp": /
-- title: untiled
- style: 'pre{ background: lightgray; }'
- style: 'img{ max-width: 100%; height: auto; }'
- style: 'video{ max-width: 100%; height: auto; }'
- style: 'h3{ border-left: solid gray; padding: 1em 0.5em; }'
+#
diff -urN v43/join_yaml.py v44/join_yaml.py
--- v43/join_yaml.py 1970-01-01 09:00:00.000000000 +0900
+++ v44/join_yaml.py 2020-01-30 22:19:42.000000000 +0900
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import arg
+import dbg
+
+def out(s, spc=0, tail='\n'):
+ dbg.out(' ' * spc + s, tail)
+
+def out_to_k(f=sys.stdin, k=''):
+ while True:
+ s = f.readline()
+ if not s or s == k:
+ break
+ out(s, 2, '')
+
+if __name__ == "__main__":
+ # ./join_yaml.py [-t title] [-h head.yaml]
+ # cat head.yaml body.yaml | ./join_yaml.py [-t title]
+
+ a = arg.new()
+
+ out('html:')
+ out('- head:')
+
+ title = a.pop_str('-t')
+ if title:
+ out('- title: ' + title, 2)
+
+ f = sys.stdin
+ head = a.pop_str('-h')
+ if head:
+ paths = [ head, os.path.join( os.path.dirname(__file__), os.path.basename(head) ) ]
+ for path in paths:
+ if os.path.exists(path):
+ f = open(path, 'r')
+ if f:
+ break
+ if not f:
+ dbg.err_exit('not found header yaml file')
+
+ out_to_k(f, '#\n')
+
+ out('- body:')
+ out_to_k()
+# EOF
diff -urN v43/to_html.py v44/to_html.py
--- v43/to_html.py 2020-01-24 11:42:20.000000000 +0900
+++ v44/to_html.py 2020-01-30 22:19:06.000000000 +0900
@@ -1,21 +1,27 @@
#!/usr/bin/env python
import sys
-import subprocess
+import arg
+import cmd_ut
+
+cmd_py = cmd_ut.cmd_py
if __name__ == "__main__":
- n = len(sys.argv)
- if n < 3:
- print( 'Usage: {} head.yaml body.txt [title]'.format( sys.argv[0] ) )
- sys.exit(1)
-
- title = sys.argv[3] if n > 3 else ''
-
- cmd_title = "sed 's/^- title: .*/- title: {}/'".format(title) if title else 'cat'
- cmd_hd = 'cat {} | {} | ./ezhtml.py y'.format( sys.argv[1], cmd_title )
-
- cmd = "( echo '<html>' ; {} ; echo '<body>' ; ./ezmd.py < {} | ./ezhtml.py y ; echo '</body></html>' ) | nkf -j";
- cmd = cmd.format( cmd_hd, sys.argv[2] )
- #print(cmd)
- subprocess.call(cmd, shell=True)
+ a = arg.new()
+
+ title = a.pop_str('-t')
+ if title:
+ title = '-t ' + title
+
+ head = a.pop_str('-h')
+ if head:
+ head = '-h ' + head
+
+ out = a.pop_str('-o', 'index.html')
+
+ body = a.pop('index.txt')
+
+ fmt = '{} < {} | {} {} {} | {} y > {}'
+ cmd = fmt.format( cmd_py('ezmd'), body, cmd_py('join_yaml'), title, head, cmd_py('ezhtml'), out )
+ cmd_ut.call(cmd)
# EOF
$ cat v44.patch | patch -p1
例えば最新版を次のような手順でダウンロードして、使えるようにしておきます。
$ cd /home/hoge $ mkdir kon_ut $ cd kon_ut $ wget http://kondoh.html.xdomain.jp/kon_ut/empty.py $ wget http://kondoh.html.xdomain.jp/kon_ut/dbg.py $ wget http://kondoh.html.xdomain.jp/kon_ut/thr.py $ wget http://kondoh.html.xdomain.jp/kon_ut/cmd_ut.py $ wget http://kondoh.html.xdomain.jp/kon_ut/io_ut.py $ wget http://kondoh.html.xdomain.jp/kon_ut/chat_conn.py $ wget http://kondoh.html.xdomain.jp/kon_ut/nkf.py $ wget http://kondoh.html.xdomain.jp/kon_ut/arg.py 例えば $ python -m site --user-site /Users/hoge/Library/Python/3.6/lib/python/site-packages $ ls /Users/hoge/Library/Python/3.6/lib/python/site-packages ls: No such file or directory ディレクトリが無かったら作っておく $ mkdir -p $(python -m site --user-site) $ pwd /home/hoge/kon_ut なので echo $(pwd) > $(python -m site --user-site)/kon_page.pth などと.pthファイルを生成
これでたぶん、どこにいてもkon_utのファイルがimportできます。
$ cd /tmp $ python >>> import dbg >>> dbg.out('hoge') hoge
kon_utと同様に、ezmdも使えるようにしておきます。
$ mkdir /home/hoge/ezmd $ cp ezmd.py join_yaml.py to_html.py head.yaml /home/hoge/ezmd/ $ cp ezhtml.py /home/hoge/ezmd/ # !!! (nkf.pyはkon_ut側にとりこまれたので既に使えるはずです) 例えば $ python -m site --user-site /Users/hoge/Library/Python/3.6/lib/python/site-packages $ ls $(python -m site --user-site) kon_page.pth $ cat $(python -m site --user-site)/kon_page.pth /home/hoge/kon_ut $ ならば $ pwd /home/hoge/ezmd $ echo $(pwd) >> $(python -m site --user-site)/kon_page.pth $ cat $(python -m site --user-site)/kon_page.pth /home/hoge/kon_ut /home/hoge/ezmd $
例えば
としたら
$ python -m to_html -t sample -h head.yaml -o sample.html sample.txt $ cat sample.html <html><head><title>sample</title> <meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp"> <style>pre{ background: lightgray; }</style> <style>img{ max-width: 100%; height: auto; }</style> <style>video{ max-width: 100%; height: auto; }</style> <style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head> <body><h1><a name="c_1_0">sample</a></h1> <p>hogehoge</p> <h2><a name="c_2_1">foo</a></h2> <p>fugafuga</p> <h3><a name="c_3_2">bar</a></h3> <p>---</p> <table border="1" cellspacing="0"><tr><th>foo</th> <th>bar</th></tr> <tr><td>hogehoge</td> <td>fugafuga</td></tr></table> <p>---</p></body></html>
sample.html
<html><head><title>sample</title>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>video{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head>
<body><h1><a name="c_1_0">sample</a></h1>
<p>hogehoge</p>
<h2><a name="c_2_1">foo</a></h2>
<p>fugafuga</p>
<h3><a name="c_3_2">bar</a></h3>
<p>---</p>
<table border="1" cellspacing="0"><tr><th>foo</th>
<th>bar</th></tr>
<tr><td>hogehoge</td>
<td>fugafuga</td></tr></table>
<p>---</p></body></html>
-h 指定の head.yaml がカレントディレクトリに無ければ、
先の例で /home/hoge/ezmd/ にダウンロードした head.yaml が使われます。
h1, h2, h3, ... の見出しから自動生成するアンカー文字列の形式が
c_<見出しのh1,h2,..の数字>_<先頭からの総番号>
のせいで、リンク先をURLで示したいときに、解りにくい問題があります。
「バージョン21 (a (name))」で述べてる通りです。
安易に、見出しの内容の1行目がASCIIコードだけなら、 何とかしてみました。
そうで無ければ従来通りの解りにくいアンカー文字列のままです。
スペースを'_'に変換した上で、 既に使用されていたら '_2', '_3', ... を追加してみて、 使われていないものを探します。
v45.patch
diff -ur v44/ezmd.py v45/ezmd.py
--- v44/ezmd.py 2020-01-24 12:06:55.000000000 +0900
+++ v45/ezmd.py 2020-02-15 11:15:17.000000000 +0900
@@ -693,12 +693,28 @@
macro_dic_update(buf)
return
+ def make_name(s, dv_name):
+ lst = s.strip().split('\n')
+ if not lst:
+ return dv_name
+ s = lst[0]
+ if not all( map( lambda c: ord(c) < 128, s ) ):
+ return dv_name
+ s = s.replace(' ', '_')
+ names = list( map( lambda hd_name: hd_name[2], hd_names ) )
+ i = 2
+ while s in names:
+ s += '_{}'.format(i)
+ i += 1
+ return s
+
if mode in heads:
buf = lst_strip(buf)
buf = cut_empty(buf)
s = ''.join(buf)
(h_i, n) = ( int(mode[1:]), len(hd_names) )
name = 'c_{}_{}'.format(h_i, n)
+ name = make_name( s, name )
outbuf.append( tag_new( mode, {}, tag_new('a', {'name': name}, s) ) )
hd_names.append( (h_i, n, name, s) )
$ cat v45.patch | patch -p1
例えば
$ cat hoge.txt h1 hoge index 2: h2 fuga fuga fuga h2 foo foo foo h3 bar bar bar h2 ホゲ ホゲホゲ h3 フガ フガ ----
$ python -m to_html -t hoge -h head.yaml -o hoge.html hoge.txt $ cat hoge.html <html><head><title>hoge</title> <meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp"> <style>pre{ background: lightgray; }</style> <style>img{ max-width: 100%; height: auto; }</style> <style>video{ max-width: 100%; height: auto; }</style> <style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head> <body><h1><a name="hoge">hoge</a></h1> <ul><li><a href="#fuga">fuga</a> <li><a href="#foo">foo</a> <ul><li><a href="#bar">bar</a></ul> <li><a href="#c_2_4">ホゲ</a> <ul><li><a href="#c_3_5">フガ</a></ul></ul> <h2><a name="fuga">fuga</a></h2> <p>fuga fuga</p> <h2><a name="foo">foo</a></h2> <p>foo foo</p> <h3><a name="bar">bar</a></h3> <p>bar bar</p> <h2><a name="c_2_4">ホゲ</a></h2> <p>ホゲホゲ</p> <h3><a name="c_3_5">フガ</a></h3> <p>フガ</p> <p><hr></p></body></html>
hoge.html
<html><head><title>hoge</title>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>video{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head>
<body><h1><a name="hoge">hoge</a></h1>
<ul><li><a href="#fuga">fuga</a>
<li><a href="#foo">foo</a>
<ul><li><a href="#bar">bar</a></ul>
<li><a href="#c_2_4">ホゲ</a>
<ul><li><a href="#c_3_5">フガ</a></ul></ul>
<h2><a name="fuga">fuga</a></h2>
<p>fuga fuga</p>
<h2><a name="foo">foo</a></h2>
<p>foo foo</p>
<h3><a name="bar">bar</a></h3>
<p>bar bar</p>
<h2><a name="c_2_4">ホゲ</a></h2>
<p>ホゲホゲ</p>
<h3><a name="c_3_5">フガ</a></h3>
<p>フガ</p>
<p><hr></p></body></html>
to_html.py のパラメータ指定のうちで、 ヘッダ部分のタイトルは、ページによって個別に違います。
ここはデフォルトの指定はあまり意味がなく、個別に指定が必要で面倒です。
特に指定が無ければデフォルトの動作として、 bodyの中のh1タグから拾ってくるようにしてみました。
これで、お決まりのhead.yamlの使用と、 index.txtからindex.htmlの生成の場合は、 to_html.py の実行だけで何とかなります。
日本語はISO-2022-JPだけ試し確認してみました。
他のエンコーディングの場合はうまくいかないかもです ;-p)
v46.patch
diff -urN v45/get_title.py v46/get_title.py
--- v45/get_title.py 1970-01-01 09:00:00.000000000 +0900
+++ v46/get_title.py 2020-04-05 03:38:45.000000000 +0900
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+
+import nkf
+
+def get(s, dv='titile'):
+ lst = s.split( '\n' )
+ while lst.pop( 0 ) != 'h1':
+ pass
+ while lst:
+ s = lst.pop( 0 ).strip()
+ if s:
+ return s
+ return dv
+
+if __name__ == "__main__":
+ b = nkf.get_stdin()
+ opt = nkf.guess(b)
+ u8 = nkf.cvt(b, '-u')
+ s = nkf.dec(u8)
+
+ s = get( s )
+
+ u8 = nkf.enc(s)
+ b = nkf.cvt(u8, opt)
+ nkf.put_stdout(b)
+# EOF
diff -urN v45/to_html.py v46/to_html.py
--- v45/to_html.py 2020-01-30 22:19:06.000000000 +0900
+++ v46/to_html.py 2020-04-05 03:58:15.000000000 +0900
@@ -6,21 +6,28 @@
cmd_py = cmd_ut.cmd_py
+add_opt = lambda opt, v: ( opt + ' ' if v else '' ) + v
+
if __name__ == "__main__":
a = arg.new()
title = a.pop_str('-t')
- if title:
- title = '-t ' + title
+ title = add_opt( '-t', title )
head = a.pop_str('-h')
- if head:
- head = '-h ' + head
+ head = add_opt( '-h', head )
out = a.pop_str('-o', 'index.html')
body = a.pop('index.txt')
+ if not title:
+ cmd = '{} < {}'.format( cmd_py( 'get_title' ), body )
+ title = cmd_ut.call( cmd, b2s=True )
+ if title:
+ title = "'{}'".format( title )
+ title = add_opt( '-t', title )
+
fmt = '{} < {} | {} {} {} | {} y > {}'
cmd = fmt.format( cmd_py('ezmd'), body, cmd_py('join_yaml'), title, head, cmd_py('ezhtml'), out )
cmd_ut.call(cmd)
$ cat v46.patch | patch -p1
ここはひとつ、このページ自身で...
$ python -m to_html
$ head index.html | nkf -u <html><head><title>簡易なおれおれマークダウン 2019秋</title> <h1><a name="c_1_0">簡易なおれおれマークダウン 2019秋</a></h1> <p><a name="c_index"></a></p> <p><details><summary>目次</summary> <ul><li><a href="#c_2_1">はじめに</a> <li><a href="#c_2_2">headとbody</a> <li><a href="#c_2_3">タグ</a> <li><a href="#c_2_4">簡易にモード切り替えで</a> <li><a href="#c_2_7">バージョン1 (h,pタグ)</a> <li><a href="#c_2_8">バージョン2 (preタグ)</a>
内部で使ってるjoin_yaml.pyの仕様を勘違いしておりました。
to_html.pyで-hによるヘッダの指定が無ければ、join_yaml.pyの標準入力に与えるデータに、 head.yamlの内容も含まれる事にしていました。
to_html.py で-hのヘッダの指定が無いときは、 -h head.yaml がデフォルトで指定される事にします。
v47.patch
diff -ur v46/to_html.py v47/to_html.py
--- v46/to_html.py 2020-04-05 03:58:15.000000000 +0900
+++ v47/to_html.py 2020-04-05 11:08:00.000000000 +0900
@@ -14,7 +14,7 @@
title = a.pop_str('-t')
title = add_opt( '-t', title )
- head = a.pop_str('-h')
+ head = a.pop_str( '-h', 'head.yaml' )
head = add_opt( '-h', head )
out = a.pop_str('-o', 'index.html')
$ cat v47.patch | patch -p1
今度こそ、このページ自身で...
$ python -m to_html
$ head index.html | nkf -u <html><head><title>簡易なおれおれマークダウン 2019秋</title> <meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp"> <style>pre{ background: lightgray; }</style> <style>img{ max-width: 100%; height: auto; }</style> <style>video{ max-width: 100%; height: auto; }</style> <style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head> <body><h1><a name="c_1_0">簡易なおれおれマークダウン 2019秋</a></h1> <p><a name="c_index"></a></p> <p><details><summary>目次</summary> <ul><li><a href="#c_2_1">はじめに</a>
アイデアを思い付いたので、久しぶりの更新です。
従来からのhrefリンクの使いづらさは
で述べてる通りです。
ふふふ。
上記リンク。うまく張れてるようですね。
従来のa hrefタグ
[[ v1 | v2 ]] <a href="v1"> v2 </a>
を拡張して
[[ @v1 | v2 ]]
を導入します。
v1がh1,h2,h3,...の文字列に該当するものがあれば、 目次で使うリンク文字列"c_xxx_yyy"に置き換えて
<a href="c_xxx_yyy"> v2 </a>
に変換します。
[[ @v1 ]]
の場合は
< href="c_xxx_yyy"> v1 </a>
に変換します。
ほとんどが、こちらの使い方だと思います。
また、上記"@v1"のv1の中にスペースがあると、うまく動作しません。
スペースは"$_"に置き換えて指定します。
冒頭のリンクの例では
[[ @バージョン45$_目次用のアンカー文字列 ]] [[ @バージョン21$_(a$_(name)) ]]
と記述して
<p><a href="#c_2_163">バージョン45 目次用のアンカー文字列</a></p> <p><a href="#c_2_48">バージョン21 (a (name))</a></p>
に変換されます。
v48.patch
diff -ur v47/ezmd.py v48/ezmd.py
--- v47/ezmd.py 2020-02-15 11:15:17.000000000 +0900
+++ v48/ezmd.py 2020-07-16 01:04:06.000000000 +0900
@@ -788,12 +788,30 @@
do_mode_ul(buf)
return outbuf.pop_tmp()
+ def a_href_at(o):
+ def to_org(s):
+ if s.startswith( '@' ):
+ s = s [ 1: ]
+ s = s.replace( '$_', ' ' )
+ return s
+
+ href = o.prop.get( 'href' )
+ href = to_org( href )
+ for (h_i, n, name, s) in hd_names:
+ if s == href:
+ o.prop[ 'href' ] = '#' + name
+ break
+ o.v = to_org( o.v )
+ return o
+
def f_o(o):
if is_lst(o):
return flat_map(f_o, o)
if is_tag(o):
if o.name == 'index':
return f( o.v )
+ if o.name == 'a' and 'href' in o.prop and o.prop.get( 'href', '' ).startswith( '@' ):
+ return a_href_at( o )
o.v = f_o( o.v )
return o
$ cat v48.patch | patch -p1
1 pass目での処理するのは無理で、 2 pass目の目次生成の処理に追加して、 紛れこませてます。
include のファイルパスが相対パスのときの、サーチパスをちょっと変えてみました。
これまで、カレントディレクトリに無かったときに、とりあえず1つ上のディレクトリ固定としてました。
実行してるezmd.pyのあるディレクトリを追加しました。
--- v48/ezmd.py 2020-07-16 01:04:06.000000000 +0900 +++ v49/ezmd.py 2020-09-06 21:26:41.000000000 +0900 @@ -215,8 +215,12 @@ ps = ('http', 'https') cmd = 'wget -q -O-' if any( map( lambda p: s.startswith(p + '://'), ps ) ) else 'cat' - if cmd == 'cat' and not os.path.exists(s): # todo - s = '../' + s + if cmd == 'cat' and not os.path.exists(s) and s[0] != '/': + for d in [ '..', os.path.dirname( __file__ ) ]: + t = os.path.join( d, s ) + if os.path.exists( t ): + s = t + break b = subprocess.check_output( cmd + ' ' + s, shell=True ) (s, nkf_opt) = nkf.to_str(b)
to_htmlのオプションもちょっとだけ変更しました。
-o の出力ファイル指定
’-' でstdout出力に
拡張子'.yaml' または、-yaml 追加でYAML形式のまま出力に
v49.patch
diff -ur v48/ezmd.py v49/ezmd.py
--- v48/ezmd.py 2020-07-16 01:04:06.000000000 +0900
+++ v49/ezmd.py 2020-09-06 21:26:41.000000000 +0900
@@ -215,8 +215,12 @@
ps = ('http', 'https')
cmd = 'wget -q -O-' if any( map( lambda p: s.startswith(p + '://'), ps ) ) else 'cat'
- if cmd == 'cat' and not os.path.exists(s): # todo
- s = '../' + s
+ if cmd == 'cat' and not os.path.exists(s) and s[0] != '/':
+ for d in [ '..', os.path.dirname( __file__ ) ]:
+ t = os.path.join( d, s )
+ if os.path.exists( t ):
+ s = t
+ break
b = subprocess.check_output( cmd + ' ' + s, shell=True )
(s, nkf_opt) = nkf.to_str(b)
diff -ur v48/to_html.py v49/to_html.py
--- v48/to_html.py 2020-04-05 11:08:00.000000000 +0900
+++ v49/to_html.py 2020-09-06 21:04:23.000000000 +0900
@@ -28,7 +28,17 @@
title = "'{}'".format( title )
title = add_opt( '-t', title )
- fmt = '{} < {} | {} {} {} | {} y > {}'
- cmd = fmt.format( cmd_py('ezmd'), body, cmd_py('join_yaml'), title, head, cmd_py('ezhtml'), out )
- cmd_ut.call(cmd)
+
+ ezhtml = cmd_py( 'ezhtml' ) + ' y'
+ if out.endswith( '.yaml' ) or a.is_pop( '-yaml' ):
+ ezhtml = 'cat'
+ if out != '-':
+ ezhtml += ' > ' + out
+
+
+ fmt = '{} < {} | {} {} {} | {}'
+ cmd = fmt.format( cmd_py('ezmd'), body, cmd_py('join_yaml'), title, head, ezhtml )
+ s = cmd_ut.call(cmd)
+ if out == '-':
+ sys.stdout.write( s.decode() )
# EOF
$ cat v49.patch | patch -p1
が、あまりにも使いにくいです。
C言語のプリプロセッサのように、 別途、単純な前処理のincludeを導入します。
include処理の推敲 から kon_ut に追加してあるので、それを使います。
include指定行は、行頭から@で始まり、続いて「@以外または空白文字以外」が1つ以上続くパターンにします。
「@以外または空白文字以外」が1つ以上続く部分が、ファイルの指定になります。
v50.patch
diff -urN v49/INC_LINK v50/INC_LINK
--- v49/INC_LINK 1970-01-01 09:00:00.000000000 +0900
+++ v50/INC_LINK 2020-09-16 21:35:46.000000000 +0900
@@ -0,0 +1,8 @@
+swbuf
+buf_NAME
+pre
+@NAME -nr
+/
+swbuf
+p
+[[ detail | [[ NAME ]] | [[ paste | buf_NAME ]] ]]
diff -urN v49/TOPE v50/TOPE
--- v49/TOPE 1970-01-01 09:00:00.000000000 +0900
+++ v50/TOPE 2020-09-16 21:35:37.000000000 +0900
@@ -0,0 +1,13 @@
+/
+swbuf
+p
+[[ detail | 更新履歴 | [[ paste | buf_update ]] ]]
+
+
+swbuf
+buf_index
+index
+ 2:
+swbuf
+p
+[[ detail | 目次 | [[ paste | buf_index ]] ]]
diff -urN v49/TOPS v50/TOPS
--- v49/TOPS 1970-01-01 09:00:00.000000000 +0900
+++ v50/TOPS 2020-09-16 21:35:35.000000000 +0900
@@ -0,0 +1,7 @@
+swbuf
+buf_update
+tbl
+tbl_ul
+||日付
+ ||変更内容
+
diff -urN v49/ezmd.py v50/ezmd.py
--- v49/ezmd.py 2020-09-06 21:26:41.000000000 +0900
+++ v50/ezmd.py 2020-09-16 21:35:43.000000000 +0900
@@ -5,7 +5,9 @@
import subprocess
import yaml
import six
+
import nkf
+import inc_ut
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
modes = heads + [ 'p', 'pre', 'ul', 'dl', 'tbl', 'index', 'swbuf', 'macro' ]
@@ -887,12 +889,18 @@
lst = list( map( rm_nl_tag, lst) )
return lst
+def inc_exp(s):
+ inc = inc_ut.new()
+ inc.search_dirs.insert( 0, os.path.dirname( __file__ ) )
+ return inc.exp( s )
+
if __name__ == "__main__":
opt_E = '-E' in sys.argv
b = nkf.get_stdin()
(s, nkf_opt) = nkf.to_str(b)
+ s = inc_exp( s )
lst = s_to_tag_lst(s, opt_E)
lst = flat_map( tag_to_dic, lst )
$ cat v50.patch | patch -p1
パッチを当てると、データテキストファイル3つも追加されます。
TOPS と TOPE は、冒頭でよく使う「更新履歴」と「目次」生成用です。
@TOPS 2019/SEP/01 新規作成 2020/SEP/01 追記 @TOPE
などと記述すると
swbuf buf_update tbl tbl_ul ||日付 ||変更内容 2019/SEP/01 新規作成 2020/SEP/01 追記 / swbuf p [[ detail | 更新履歴 | [[ paste | buf_update ]] ]] swbuf buf_index index 2: swbuf p [[ detail | 目次 | [[ paste | buf_index ]] ]]
に展開され
更新履歴
日付
変更内容 2019/SEP/01
新規作成 2020/SEP/01
追記
目次
となります。
INC_LINK は preタグでincludeしてバッファに記録しつつ、 detailタグで折り畳んで、ラベルはリンクにします。
@INC_LINK NAME=v50.patch
などと記述すると
swbuf buf_v50.patch pre @v50.patch -nr -s / swbuf p [[ detail | [[ v50.patch ]] | [[ paste | buf_v50.patch ]] ]]
に展開されて
v50.patch
diff -urN v49/INC_LINK v50/INC_LINK
--- v49/INC_LINK 1970-01-01 09:00:00.000000000 +0900
+++ v50/INC_LINK 2020-09-16 21:35:46.000000000 +0900
@@ -0,0 +1,8 @@
+swbuf
+buf_NAME
+pre
+@NAME -nr
+/
+swbuf
+p
+[[ detail | [[ NAME ]] | [[ paste | buf_NAME ]] ]]
diff -urN v49/TOPE v50/TOPE
--- v49/TOPE 1970-01-01 09:00:00.000000000 +0900
+++ v50/TOPE 2020-09-16 21:35:37.000000000 +0900
@@ -0,0 +1,13 @@
+/
+swbuf
+p
+[[ detail | 更新履歴 | [[ paste | buf_update ]] ]]
+
+
+swbuf
+buf_index
+index
+ 2:
+swbuf
+p
+[[ detail | 目次 | [[ paste | buf_index ]] ]]
diff -urN v49/TOPS v50/TOPS
--- v49/TOPS 1970-01-01 09:00:00.000000000 +0900
+++ v50/TOPS 2020-09-16 21:35:35.000000000 +0900
@@ -0,0 +1,7 @@
+swbuf
+buf_update
+tbl
+tbl_ul
+||日付
+ ||変更内容
+
diff -urN v49/ezmd.py v50/ezmd.py
--- v49/ezmd.py 2020-09-06 21:26:41.000000000 +0900
+++ v50/ezmd.py 2020-09-16 21:35:43.000000000 +0900
@@ -5,7 +5,9 @@
import subprocess
import yaml
import six
+
import nkf
+import inc_ut
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
modes = heads + [ 'p', 'pre', 'ul', 'dl', 'tbl', 'index', 'swbuf', 'macro' ]
@@ -887,12 +889,18 @@
lst = list( map( rm_nl_tag, lst) )
return lst
+def inc_exp(s):
+ inc = inc_ut.new()
+ inc.search_dirs.insert( 0, os.path.dirname( __file__ ) )
+ return inc.exp( s )
+
if __name__ == "__main__":
opt_E = '-E' in sys.argv
b = nkf.get_stdin()
(s, nkf_opt) = nkf.to_str(b)
+ s = inc_exp( s )
lst = s_to_tag_lst(s, opt_E)
lst = flat_map( tag_to_dic, lst )
diff -urN v49/INC_LINK v50/INC_LINK
--- v49/INC_LINK 1970-01-01 09:00:00.000000000 +0900
+++ v50/INC_LINK 2020-09-16 21:35:46.000000000 +0900
@@ -0,0 +1,8 @@
+swbuf
+buf_NAME
+pre
+@NAME -nr
+/
+swbuf
+p
+[[ detail | [[ NAME ]] | [[ paste | buf_NAME ]] ]]
diff -urN v49/TOPE v50/TOPE
--- v49/TOPE 1970-01-01 09:00:00.000000000 +0900
+++ v50/TOPE 2020-09-16 21:35:37.000000000 +0900
@@ -0,0 +1,13 @@
+/
+swbuf
+p
+[[ detail | 更新履歴 | [[ paste | buf_update ]] ]]
+
+
+swbuf
+buf_index
+index
+ 2:
+swbuf
+p
+[[ detail | 目次 | [[ paste | buf_index ]] ]]
diff -urN v49/TOPS v50/TOPS
--- v49/TOPS 1970-01-01 09:00:00.000000000 +0900
+++ v50/TOPS 2020-09-16 21:35:35.000000000 +0900
@@ -0,0 +1,7 @@
+swbuf
+buf_update
+tbl
+tbl_ul
+||日付
+ ||変更内容
+
diff -urN v49/ezmd.py v50/ezmd.py
--- v49/ezmd.py 2020-09-06 21:26:41.000000000 +0900
+++ v50/ezmd.py 2020-09-16 21:35:43.000000000 +0900
@@ -5,7 +5,9 @@
import subprocess
import yaml
import six
+
import nkf
+import inc_ut
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
modes = heads + [ 'p', 'pre', 'ul', 'dl', 'tbl', 'index', 'swbuf', 'macro' ]
@@ -887,12 +889,18 @@
lst = list( map( rm_nl_tag, lst) )
return lst
+def inc_exp(s):
+ inc = inc_ut.new()
+ inc.search_dirs.insert( 0, os.path.dirname( __file__ ) )
+ return inc.exp( s )
+
if __name__ == "__main__":
opt_E = '-E' in sys.argv
b = nkf.get_stdin()
(s, nkf_opt) = nkf.to_str(b)
+ s = inc_exp( s )
lst = s_to_tag_lst(s, opt_E)
lst = flat_map( tag_to_dic, lst )
となります。
include指示行に字下げ -s オプションを追加しました。 INC_LINKの更新 (2020/OCT/10 追加)
気になりつつ長らく放置してた問題を対策しておきます。
h1 tbl_ng tbl tbl_ul foo bar hoge fuga /
の場合
$ cat tbl_ng.txt | ./ezmd.py - h1: a name="tbl_ng": tbl_ng - table border="1" cellspacing="0": - tr: - td rowspan="2": foo - td: bar - tr: - td: hoge - td: fuga
からの
$ to_html -o - tbl_ng.txt <html><head><title>tbl_ng</title> <meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp"> <style>pre{ background: lightgray; }</style> <style>img{ max-width: 100%; height: auto; }</style> <style>video{ max-width: 100%; height: auto; }</style> <style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head> <body><h1><a name="tbl_ng">tbl_ng</a></h1> <table border="1" cellspacing="0"><tr><td rowspan="2">foo</td> <td>bar</td></tr> <tr><td>hoge</td> <td>fuga</td></tr></table></body></html>
$ to_html -o tbl_ng.html tbl_ng.txt
tbl_ng.html
<html><head><title>tbl_ng</title>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>video{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head>
<body><h1><a name="tbl_ng">tbl_ng</a></h1>
<table border="1" cellspacing="0"><tr><td rowspan="2">foo</td>
<td>bar</td></tr>
<tr><td>hoge</td>
<td>fuga</td></tr></table></body></html>
と、残念なbarセルのcolspan指定になっていました。
v51.patch
diff -ur v50/ezmd.py v51/ezmd.py
--- v50/ezmd.py 2020-09-16 21:35:43.000000000 +0900
+++ v51/ezmd.py 2020-09-16 22:20:28.000000000 +0900
@@ -538,7 +538,7 @@
if k in tag.prop:
cv_to_tbl( tag.prop.get(k), x+1, tbl )
else:
- w = w - x + 1
+ w = gw - x
if w > 1:
prop['colspan'] = w
tbl.v.append( tag_new('tr', {}, []) )
$ cat v51.patch | patch -p1
$ cat tbl_ng.txt | ./ezmd.py - h1: a name="tbl_ng": tbl_ng - table border="1" cellspacing="0": - tr: - td rowspan="2": foo - td colspan="2": bar - tr: - td: hoge - td colspan="2": fuga
$ to_html -o - tbl_ng.txt <html><head><title>tbl_ng</title> <meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp"> <style>pre{ background: lightgray; }</style> <style>img{ max-width: 100%; height: auto; }</style> <style>video{ max-width: 100%; height: auto; }</style> <style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head> <body><h1><a name="tbl_ng">tbl_ng</a></h1> <table border="1" cellspacing="0"><tr><td rowspan="2">foo</td> <td colspan="2">bar</td></tr> <tr><td>hoge</td> <td colspan="2">fuga</td></tr></table></body></html>
$ to_html -o tbl_ok.html tbl_ng.txt
tbl_ok.html
<html><head><title>tbl_ng</title>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>video{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head>
<body><h1><a name="tbl_ng">tbl_ng</a></h1>
<table border="1" cellspacing="0"><tr><td rowspan="2">foo</td>
<td colspan="2">bar</td></tr>
<tr><td>hoge</td>
<td colspan="2">fuga</td></tr></table></body></html>
OK。
OK。じゃなかったです。見逃していました。
$ cat tbl_ng.txt | ./ezmd.py - h1: a name="tbl_ng": tbl_ng - table border="1" cellspacing="0": - tr: - td rowspan="2": foo - td colspan="2": bar - tr: - td: hoge - td colspan="2": fuga
末尾の fuga は colspan 1 になるはずです。
ソースを追いかけてみると、tbls_join()関数にバグがありました。
v52.patch
diff -ur v51/ezmd.py v52/ezmd.py
--- v51/ezmd.py 2020-09-16 22:20:28.000000000 +0900
+++ v52/ezmd.py 2020-09-18 21:07:16.000000000 +0900
@@ -573,8 +573,8 @@
trs = []
for tbl in tbls:
+ add = w_max - w_get( tbl )
for tr in tbl.v:
- add = w_max - w_get(tr)
tail = tr.v[-1]
k = 'colspan'
w = tail.prop.get(k, 1) + add
$ cat tbl_ng.txt | ./ezmd.py - h1: a name="tbl_ng": tbl_ng - table cellspacing="0" border="1": - tr: - td rowspan="2": foo - td colspan="2": bar - tr: - td: hoge - td: fuga
$ to_html -o tbl_ok2.html tbl_ng.txt
tbl_ok2.html
<html><head><title>tbl_ng</title>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<style>pre{ background: lightgray; }</style>
<style>img{ max-width: 100%; height: auto; }</style>
<style>video{ max-width: 100%; height: auto; }</style>
<style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head>
<body><h1><a name="tbl_ng">tbl_ng</a></h1>
<table border="1" cellspacing="0"><tr><td rowspan="2">foo</td>
<td colspan="2">bar</td></tr>
<tr><td>hoge</td>
<td>fuga</td></tr></table></body></html>
今度は大丈夫だろうか?
inc_ut.py にバッファの機能を追加した影響で、 自動的にezmd.pyもincludeがバッファ対応になりました。
詳細は include処理の推敲 をご参照ください。
v53.patch
diff -urN v52/DETAIL v53/DETAIL
--- v52/DETAIL 1970-01-01 09:00:00.000000000 +0900
+++ v53/DETAIL 2020-09-24 22:52:32.000000000 +0900
@@ -0,0 +1,6 @@
+swbuf
+buf_NAME
+@NAME
+swbuf
+p
+[[ detail | LABEL | [[ paste | buf_NAME ]] ]]
として
DETAIL
swbuf
buf_NAME
@NAME
swbuf
p
[[ detail | LABEL | [[ paste | buf_NAME ]] ]]
を追加してみます。
例えば
@>sample-1 tbl tbl_ul ||名前 ||値 hoge 123 / @< @DETAIL LABEL=サンプル-1 NAME=sample-1
と書けば
サンプル-1
名前
値 hoge
123
となります。
従来からの
swbuf buf_sample-2 tbl tbl_ul ||名前 ||値 hoge 123 / p [[ detail | サンプル-2 | [[ paste | buf_sample-2 ]] ]]
からの
サンプル-2
名前
値 hoge
123
と、どう違うのかと言われると、まぁほぼ同じなのですが、、、
こうも書けるようになった、という事で。
kon_ut の inc_ut.py に機能を追加しました。
'@>'でバッファ名を指定しなければ、自動生成されます。
include指示行で'$$'として最後に登録したバッファ名を参照できます。
@> tbl tbl_ul ||名前 ||値 hoge 123 / @< @DETAIL LABEL=サンプル-3 NAME=$$
とも書けるようになりました。
サンプル-3
名前
値 hoge
123
となります。
v54.patch
diff -ur v53/get_title.py v54/get_title.py
--- v53/get_title.py 2020-04-05 03:38:45.000000000 +0900
+++ v54/get_title.py 2020-09-26 03:22:50.000000000 +0900
@@ -2,9 +2,9 @@
import nkf
-def get(s, dv='titile'):
+def get(s, dv='title'):
lst = s.split( '\n' )
- while lst.pop( 0 ) != 'h1':
+ while lst and lst.pop( 0 ) != 'h1':
pass
while lst:
s = lst.pop( 0 ).strip()
typoを見つけたので修正。
ついでに、h1がいつのまにか必須になっていた原因がわかったので、 修正しました。
[[ path_to_html | ラベル ]] [[ url_to_html | ラベル ]]
の場合に、ラベルの文字列を調べて書くのが面倒です。
'|' の後のラベルの箇所を省略すると、 できるだけ頑張って、 HTMLデータのheaderからtitleを探すようにしてみました。
v55.patch
diff -ur v54/ezmd.py v55/ezmd.py
--- v54/ezmd.py 2020-09-18 21:07:16.000000000 +0900
+++ v55/ezmd.py 2020-10-03 12:57:47.000000000 +0900
@@ -8,6 +8,7 @@
import nkf
import inc_ut
+import html_ut
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
modes = heads + [ 'p', 'pre', 'ul', 'dl', 'tbl', 'index', 'swbuf', 'macro' ]
@@ -265,6 +266,9 @@
r = do_detail(v2)
if r:
return r
+
+ if v2 == '':
+ v2 = html_ut.get_title( v1 )
return tag_new('a', {'href': v1}, v2) if v1 else v2
def do_br(s):
tilteを探す部分は、 pythonのユーティリティ・プログラム 2020冬 に html_ut.py として追加してみました。
[[ path ]]
のように'|' のない場合は、 従来通り
[[ path | path ]]
扱いのままです。
include指示行に字下げ -s オプションを追加しました。
v56.patch
diff -ur v55/INC_LINK v56/INC_LINK
--- v55/INC_LINK 2020-09-16 21:35:46.000000000 +0900
+++ v56/INC_LINK 2020-10-10 04:33:14.000000000 +0900
@@ -1,7 +1,7 @@
swbuf
buf_NAME
pre
-@NAME -nr
+@NAME -nr -s
/
swbuf
p
ファイル中に行頭から’/'だけの行があると、preの末尾として判定されてしまい、 意図したように動作しない事があったので、対策してます。
v57.patch
diff -urN v56/DETAIL_MODE v57/DETAIL_MODE
--- v56/DETAIL_MODE 1970-01-01 09:00:00.000000000 +0900
+++ v57/DETAIL_MODE 2020-10-10 19:48:00.000000000 +0900
@@ -0,0 +1,3 @@
+[[ detail | LABEL | [[ mode | ^\
+@NAME -tc
+$ ]] ]]
DETAIL_M
[[ detail | LABEL | [[ mode | ^\
@NAME -tc
$ ]] ]]
を追加してみました。
DETAIL
swbuf
buf_NAME
@NAME
swbuf
p
[[ detail | LABEL | [[ paste | buf_NAME ]] ]]
swbuf
buf_NAME
@NAME
swbuf
p
[[ detail | LABEL | [[ paste | buf_NAME ]] ]]
と結果としての機能は同様ですが、swbufを直接使わないで実現してます。
例えば
@> tbl tbl_ul ||name ||value hoge 123 / @< @DETAIL_M LABEL=table NAME=$$
は
[[ detail | table | [[ mode | ^\ tbl \ tbl_ul \ ||name \ ||value \ hoge \ 123 \ / \ $ ]] ]]
に展開されて
table
name
value hoge
123
になります。
既出の DETAIL では
@> tbl tbl_ul ||name ||value hoge 123 / @< @DETAIL LABEL=table NAME=$$
は
swbuf buf_tMp_1234 tbl tbl_ul ||name ||value hoge 123 / swbuf p [[ detail | table | [[ paste | buf_tMp_1234 ]] ]]
に展開されて
table
name
value hoge
123
になります。
v58.patch
diff -urN v57/INDEX v58/INDEX
--- v57/INDEX 1970-01-01 09:00:00.000000000 +0900
+++ v58/INDEX 2020-10-22 03:26:16.000000000 +0900
@@ -0,0 +1,7 @@
+swbuf
+buf_index
+index
+ 2:
+swbuf
+p
+[[ detail | 目次 | [[ paste | buf_index ]] ]]
INDEX
swbuf
buf_index
index
2:
swbuf
p
[[ detail | 目次 | [[ paste | buf_index ]] ]]
を追加してみました。
TOPS
swbuf
buf_update
tbl
tbl_ul
||日付
||変更内容
TOPE
/
swbuf
p
[[ detail | 更新履歴 | [[ paste | buf_update ]] ]]
swbuf
buf_index
index
2:
swbuf
p
[[ detail | 目次 | [[ paste | buf_index ]] ]]
の後半に含まれてますが、目次単体で使いたい場面用です。
v59.patch
diff -ur v58/ezmd.py v59/ezmd.py
--- v58/ezmd.py 2020-10-03 12:57:47.000000000 +0900
+++ v59/ezmd.py 2020-10-23 05:19:00.000000000 +0900
@@ -9,6 +9,8 @@
import nkf
import inc_ut
import html_ut
+import tm_ut
+import cmd_ut
heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ]
modes = heads + [ 'p', 'pre', 'ul', 'dl', 'tbl', 'index', 'swbuf', 'macro' ]
@@ -266,6 +268,12 @@
r = do_detail(v2)
if r:
return r
+ if v1 == 'eval':
+ return do_v1v2( 'mode', eval( v2 ) )
+ if v1 == 'date':
+ return do_v1v2( 'eval', 'tm_ut.date432()' )
+ if v1 == 'cmd':
+ return do_v1v2( 'eval', 'cmd_ut.call( "{}", b2s=True )'.format( v2 ) )
if v2 == '':
v2 = html_ut.get_title( v1 )
個人的によく使う日付の形式が
2021/FEB/23
なので
pythonのユーティリティ・プログラム 2020冬 の tm_ut.py に date432() なる関数を追加してみました。
それを利用して、そのまま文書に貼り付けたく、 「例の形式」で指定できるようにしました。
[[ date ]]
せっかくなので、それを実現するために、
[[ eval | 文字列 ]]
も追加です。
eval()結果は文字列が返ることが前提です。
内部で eval( 文字列 ) を実行し、 その結果の文字列を、内部的に
[[ mode | 結果の文字列 ]]
としてタグにしてます。
[[ date ]]
の場合は、ezmd.pyでimport tm_utしておいて、内部で
[[ eval | tm_ut.date432() ]]
相当の処理となってます。
この際なので、ezmd.pyにimport cmd_utも追加しました。
[[ cmd | コマンド文字列 ]]
で、コマンド文字列を実行し、結果として表示される文字列が
[[ mode | 結果として表示される文字列 ]]
として取り込まれます。
[[ cmd | date ]]
は
2021年 2月23日 火曜日 17時46分26秒 JST
になります。
v60.patch
diff -urN v59/INC_LINK_BN v60/INC_LINK_BN
--- v59/INC_LINK_BN 1970-01-01 09:00:00.000000000 +0900
+++ v60/INC_LINK_BN 2020-11-17 23:54:24.000000000 +0900
@@ -0,0 +1,8 @@
+swbuf
+buf_NAME
+pre
+@NAME -nr -s
+/
+swbuf
+p
+[[ detail | [[ NAME | $]] | [[ paste | buf_NAME ]] ]]
diff -urN v59/ezmd.py v60/ezmd.py
--- v59/ezmd.py 2020-10-23 05:19:00.000000000 +0900
+++ v60/ezmd.py 2020-11-17 23:51:13.000000000 +0900
@@ -277,6 +277,8 @@
if v2 == '':
v2 = html_ut.get_title( v1 )
+ elif v2 == '$':
+ v2 = os.path.basename( v1 )
return tag_new('a', {'href': v1}, v2) if v1 else v2
def do_br(s):
[[ ../../foo/bar/hoge.c ]]
のリンクにすると、格好悪いので
[[ ../../foo/bar/hoge.c | hoge.c ]]
などとラベルを整えたりします。
hoge.c の basename の部分が長いと面倒なので、 $ を書くと、basename を取り出してくれるようにしておきます。
これで
[[ ../../foo/bar/hoge.c | $ ]]
でOKです。
@INC_LINK NAME=xxx
のリンクラベルも、basename $ 指定にした版を INC_LINK_BN として追加しておきます。
INC_LINK_BN
swbuf
buf_NAME
pre
@NAME -nr -s
/
swbuf
p
[[ detail | [[ NAME | $]] | [[ paste | buf_NAME ]] ]]
の都合で機能追加というか、手を入れてみました。
実はezmd.pyの対応だけでは済まずに、 簡易なHTMLパーサ 2018秋 側も、 セットでてを入れてます。
"pre"の中でHTMLの仕様の下線<u>...</u>などをそのまま使用したく。
"pre"直後の行が"bare"だけの行になっていると、以降、その"pre"の中では、 <u>...</u>などがそのまま記述できます。
ezmd.pyとしては、preタグのプロパティにbare="True"を追加するだけの変更になります。
下流のezhtml.py側で、プロパティにbare="True"がついてると、 &, <, > の3つの文字について、"&", "<", ">" のエンコード処理をせずに素通ししてHTMLを生成します。
v61.patch
diff -ur v60/ezmd.py v61/ezmd.py
--- v60/ezmd.py 2020-11-17 23:51:13.000000000 +0900
+++ v61/ezmd.py 2021-02-23 17:15:48.000000000 +0900
@@ -754,11 +754,16 @@
if lst:
outbuf.append( tag_new('p', {}, lst) )
elif mode == 'pre':
+ prop = {}
+ bare = ( buf and buf[0] == 'bare' )
+ if bare:
+ buf = buf[1:]
+ prop[ 'bare' ] = True
buf = cut_ht_empty(buf)
if buf:
buf = cut_verb_idt(buf)
s = '\n'.join(buf) + '\n'
- outbuf.append( tag_new('pre', {}, s) )
+ outbuf.append( tag_new('pre', prop, s) )
elif mode == 'ul':
do_mode_ul(buf)
elif mode == 'dl':
pre foo <u>bar</u> hoge /
では
foo <u>bar</u> hoge
となりますが、
pre bare foo <u>bar</u> hoge /
では
foo bar hoge
となります。