#author("2026-02-09T00:16:12+09:00","","") #author("2026-02-11T06:45:39+09:00","","") #contents ---- * TIRとは [#gb1ebbb2] TIR - Tabular Intermediate Representation 複数の表とテキストを含む中間表現。 次の3種類の要素で構成される。 - 先頭1行目がfile_attrオブジェクト(バージョン情報など) - plainブロック(複数行のテキストで構成される) - gridブロック(1つの表を表す) TIRの表現形式には非正規形と正規形の2種類存在する。 - 正規形:NDJSON形式。上から1行ずつ順番に処理して後戻りを極力排除した逐次処理向けの形式 - 非正規形:NDJSON形式。parserなどが出力する形式。正規形に変換可能。 TIRは文章と表を含んだファイル(例:csv, md(gfm), html, wiki など)間の橋渡しをする役割を持つ。 またTIR形式のエディタ、ツール群を用意する。また各自エディタ、ツールを作成することができる。 初期バージョンにおいては、TIRの永続的な保存は想定しない。 次の様に短いセッションの間だけTIRは存在する。 - ファイル形式の相互変換 - エディタ・ツールで読み込んで編集して保存 従ってTIRバージョン時に後方互換は保証しない。 * TIR 正規形NDJSON(v0.1) [#g3c3abb6] - NDJSON形式([[RFC 8259:https://www.rfc-editor.org/rfc/rfc8259]] / ECMA-404)を満たす - コードはUTF8 - 各行はJSONオブジェクト - 目的:一度現れた情報を後で上書きするような仕様を極力排除する -- 逐次処理を効率的に行うため ** NDJSONオブジェクトの種類 [#oaedd5e5] - TIRにおけるオブジェクト種別は4種類に限定され、kind メンバーによって識別する。 -- { "kind":kind, ... } -- kind:= "file_attr" | "block_start" | "plain" | "grid" -- ...: メンバー名付きの値。 - file_attr: バージョン情報などファイル属性 - block_start: ブロックの開始を表す。ブロック属性を持つことができる - plain: テキスト1行を表す - grid: 表の1行を表す ** 各オブジェクト種類の出現順序 [#he6f23d8] - file_attrオブジェクトは1行目に1回だけ現れなければならない - 全体はplainブロックとgridブロックからなる - block_startはplain|gridブロックの開始を示すが省略可能。 -- csv, tsv などではblock_startは不要なので省略可能とした -- plain|gridブロックは1以上の連続したplain|gridオブジェクトからなる - plainブロックとはblock_start|plainで始まりplain以外(EOFを含む)の直前行までである - gridブロックとはblock_start|gridで始まりgrid以外(EOFを含む)の直前行までである ** blockの区切り [#d834b9af] 前後の行の種類の組み合わせとblockの状態 |CENTER:|CENTER:|CENTER:|CENTER:|CENTER:|c | 前の行 |>|>|>| 次の行 |h |~| file_attr | block_start | plain | grid |h | file_attr | ❌ | start | start | start | | block_start | ❌ | ❌ | start | start | | plain | ❌ | start | continue | start | | grid | ❌ | start | start | continue | ** file_attr [#p39fb949] - { "kind":"file_attr", "version":"tir/0.1", "file_path":"xxxx" } - ファイルの属性を表すオブジェクト - parser が作成する - tir_version:= ファイルのtirバージョン。省略不可 -- tirenvi, tir tool 群は最新バージョンだけに対応する -- 古いtirバージョンは変換ツールを使用して最新バージョンにする事 -- 現状バージョンはv0.1しかないのでバージョン変換ツールはない - file_path:= 元flatファイルの絶対パス。 -- 省略不可 -- これはパーサーが逆変換unparseをする時に元のファイルから落ちた情報を復元するのに使うことができる -- 実ファイルがない場合、わからない場合はnullを指定する ** block_start [#e868e6f8] - { "kind":"block_start", "attr":{ ... } } - ブロックの開始を示す。 - attr:ブロックの属性。 -- 属性値がなれけば省略可能。 - plainブロックには現状属性はない。 - gridブロックで次のものが意味を持つ。 -- column_align:= [ "left", "right", "center", "", ... ] --- セル内配置:それぞれ、左寄せ、右寄せ、中央、デフォルト --- この4種類以外はデフォルトと解釈する -- column_width:= [ 10, 8, , ... ] --- 0-255の整数値。 --- 0:デフォルト値。列幅自動決定。自動決定の場合表を全部スキャンしないと決められない。 --- !=0:モノスペースでの列幅 -- 列数は表の列数と一致する ** plain [#c4f68b56] - "kind":"plain", "line":"xxxxx" - プレーンテキストを表す行 - 内容はline。長さ0以上の文字列。 ** grid [#ae2ff1b4] - { "kind":"grid", "row":[ "aaa", "bbb", "ccc" ] } - 1行分の表データー。 - row: 長さ1以上の文字列配列。改行(\n)を含むことができる。 - row: 行内容を表す。列の数だけ値を並べる。 - row: 一つの表ブロック内で列数が一致しなければならない -- 一致しないと後戻りが必要になるため ** 書式拡張案 [#wb5beead] - [[PukiWiki仕様:http://wiki.kibi2.com/html/?FormattingRules#k7c49df4]] - 列ごとの書式指定:配置、前|背景色、フォントサイズ、幅 - セルごとの書式指定:配置、前|背景色、フォントサイズ - 列、行セル結合(span) - header, footer 複数バラバラ指定 PukiWikiではできないこと - 固定行 - caption tirenviでサポートしようとするとセル書式はセル内に埋め込む必要がある - 列削除で自然に連動して消える * TIR 非正規形NDJSON(v0.1) [#yacb3175] ** TIR 正規形NDJSONとの相違点 [#oa5fc65e] - 1行目はkind:file_attrでなければならないが2行目以降に現れても良い -- catなどでの連結を想定している -- 2行目以降にkind:file_attrがあった場合ブロック区切りとして働く -- バージョンが異なるtirを連結する場合は、連結する前にツールを使用してバージョンを合わせておくこと -- 現状バージョンはv0.1しかないのでバージョン変換ツールはまだない - どのオブジェクトがどの順序で現れてもエラーにはならない - gridブロック内で列数が一致する必要はない -- 正規化により列数を合わせる->正規化処理を参照 -- 正規化で列数と一致するようデフォルト値を補う。多すぎると無視される。 * 正規化処理 [#ge4fd1be] - 1行目以外のkind:file_attrを削除する - plain|gridオブジェクトの数が0のplain|grid blockを削除する - gridブロック内girdオブジェクトの最大列数をgridブロックの列数とする。 - 列数が少ないgridオブジェクトは空文字を追加して列数を合わせる -- これにより連続したgridオブジェクトの列数は同じになる -- &color(,orange){連続したgridオブジェクトが別表になることはない}; - gridオブジェクトのrowは全て文字列にする - column_align, column_witdhの列数を合わせる -- 短ければデフォルト値を加える -- 長ければ削除する * 独自拡張・独自ツール [#m44545ec] - kindは4種類に限定し、増やすことはできない。 -- 独自ツールでkindを増やしたい場合は次の独自メンバー名を使って工夫して作成すること -- 例 { "kind":"block_start", "_mykind":"code-block" } { "kind":"plain", "_mykind":"code-block", "line":"function foo()" } -- 次項「各オブジェクト種類の出現順序」では、これら4種類の出現順が持つ意味を規定している。 -- kindを拡張すると、この順序規則を大幅に改訂する必要があり、仕様および実装が複雑化する。 -- 一方で、その表現力の多くは独自メンバー名によって代替可能であるため、kind拡張のメリットは小さい。 - "_"で始まるメンバー名を追加してよい -- 他の独自ツールと競合しないように配慮すること -- 正規メンバー名は"_"で始まらない。将来の競合を避ける目的 * 独自ツール開発 [#tfb6fb9c] - file_attrオブジェクトはなるべくそのまま出力する - ツールで使用しないメンバー名が入力にあれば加工せずそのまま出力する -- メンバー名が増えた場合、対応しないツール経由でも動作させる目的 * TIR パーサー仕様 [#v47fe23e] - コマンド形式 - 名前:tir-で始まる。以下例として tir-md とする。 - 使用例 -- tir-md parse file :mark down 形式のfileを読み込んでNDJSON形式でstdoutに書き出す -- 成功した場合はstderrには何も表示しない。失敗した場合はstderrに表示する。 --- これで成功、失敗を見分ける -- tir-md unparse file :標準入力からNDJSON形式で読み込んでfileに書き出す -- 成功した場合はstderrには何も表示しない。失敗した場合はstderrに表示する。 --- これで成功、失敗を見分ける -- tir-md --version:バージョン表示 -- 自作する場合は独自サブコマンドは作らないこと。オプションで対応すること。 -- 自作する場合はparse fileは必ず作成すること。他は任意 * TIR ツール仕様 [#x7bced2e] - コマンド形式 - tir - 基本的にstdinからNDJSONを読み込んで加工した後stdoutに書き出す。 - 使用例 - tir normalize : stdin からNDJSON を読み込んで正規化(列数を揃える)してstdout に出力する - 以下案 - tir block select n - tir show-outline - tir block n row delete m - tir block n row insert m -- target action place ** パーサーの使い方案 [#n6922602] - パーサーのunparseは正規化DNJSONを前提に作ると良いでしょう。 - tir toolsは正規化DNJSONを前提に作ると良いでしょう。 - パーサーが出力するDNJSONは正規化されていません * tirエディタ開発のヒント [#t9c3074c] tirエディタは最終的にtir仕様に違反したファイルを作ってはいけない。それ以外は自由に作って良い。エディタ開発のヒントとしてvim用エディタtirenviの挙動を書いておく。 ** 自由に編集できるところとできないところがある [#pd74feaa] - 自由に編集できないところは見た目で区別する -- 文字属性:背景色、前景色、サイズ、太字、イタリック、回転、hidden? -- 別の文字を表示する?conceal?前景色=背景色 -- CRC ** fire_attr [#w0ff701e] - エディタ上では表示しない -- ユーザーが編集できる項目がないため ** grid [#v1370a81] - 表を破壊する操作(表破壊)は禁止する - 表破壊とは -- 表内で列数が不一致の行を作ること -- 判定方法:隣接したgird objectの列数が異なる ** block_start [#obabb93d] - 表に属性をつけるとblock_startで覚える -- block_startがなければblock_startを追加する - 表の途中にblock_startを追加すると表が分離する - 列数が異なる表と表の間のblock_startを削除する事はできない -- 表破壊チェックに引っかかるため自動でundoする - 列数が同じ表と表の間のblock_startを削除すると表が合体する -- 表破壊チェックに引っかからないため - 行数が0のblockは保存しない - 列属性は列データとして持たせる -- こうすることで列を削除すると自然に列属性も削除できる - 属性の直接編集を禁止する -- 書式を壊さないように編集することが難しいため -- 編集を検知できるようにcrcコードをつける -- 編集意欲を削ぐためbase64変換する * grid block 識別方法 [#e0d26657] - 連続した最長のgrid objectがgrid block