コンテンツにスキップ

部品ごとの関数(TSV と本文インデックス)

扱うこと: TSV の名前と場所・整形(fs.ps1・index_name.ps1・text.ps1・tsv_file.ps1)、インデックスへの配置(index_store.ps1)、本文インデックスの形式と読み書き(content_index_format.ps1・content_index_store.ps1)の関数一覧。扱わないこと: 検索そのものの関数(部品ごとの関数(検索・スレッド・元のファイル・画面))。先に読むページ: 部品から関数一覧を引く。

TSV の名前と場所(shared/core/fs.ps1・tebunko/index/index_name.ps1)

関数 入力 出力 概要 詳細 使用元
encodeIndexPlace place string TSV のファイル名に入れる場所を符号化する(ファイル名禁止文字・制御文字・_・% を %XX に) インデックスのファイルの形 toIndexFileName
decodeIndexPlace place string encodeIndexPlace の %XX を元に戻す(それ以外の % はそのまま) 同上 convertIndexFileNameToPlace
convertPlaceBaseToFixedFileName base string(固定名 / 空) 場所の元の名前(ページ001 など)が決まった種類なら、固定の英語のファイル名(page_001 など)を返す。決まった種類でなければ空文字列 インデックスのファイルの形 toIndexFileName
convertFixedFileNameToPlaceBase fileBase string(元の名前 / 空) convertPlaceBaseToFixedFileName の逆(page_001 → ページ001)。固定名でなければ空文字列 同上 convertIndexFileNameToPlace
toIndexFileName place string インデックスの TSV のファイル名 <場所>.tsv(場所は convertPlaceBaseToFixedFileName の固定名、無ければ encodeIndexPlace)。図形・コメント・ヘッダー・フッターは、末尾に英語の種類 [shape] [comment] [header_footer] を付ける。元のファイル名はフォルダ名にするため入れない。$maxFileNameLength(255)文字を超えれば例外 インデックスのファイルの形 インデックス作成(Excel・Word・PowerPoint)
convertIndexFileNameToPlace fileNameWithoutExtension string toIndexFileName の逆。図形・コメント・ヘッダー・フッターの種類([shape] [comment] [header_footer])を外してから、固定名なら convertFixedFileNameToPlaceBase、そうでなければ decodeIndexPlace で場所の元の名前に戻す 同上 getIndexFolderBooks
splitObjectPlace place @{Base; Kind} 図形・コメント・ヘッダー・フッターの場所(<元の場所>[図形] 等)を、元の場所と種類に分ける。ふつうの場所は Kind が空 インデックスのファイルの形「図形・コメントの場所」 元のファイルを開く、convertPlaceToContentIndexMeta
newObjectPlaceKindPattern kinds(省略は全部) string 場所の末尾の種類([図形] [埋め込み<N>] など)だけを当てる正規表現の文字列を、placeKindFileNames の表から組み立てる。検索から外す場所(newPlaceExclude)と画面の判定(HitRow.ObjectPlaceRegex)が使う インデックスのファイルの形「図形・コメントの場所」 newPlaceExclude、画面(HitRow)
describePlace book, place @{Place; Kind} 場所ごとの表記と種別(見出しの要約・検索結果ファイル・コピーに出す文字。[シート]売上・図形、3 ページ(目安)・本文 など) 出力フォーマット 画面・toResultLine
describeHitPlace place, isExcel, isObjectPlace, matchCell, matchCount, lineNumber, isText(既定 $false) string 結果の表の「場所」列・プレビューの題に出す、行ごとの表記(Excel は場所ごとの表記にセル番地を足す。[シート]売上!B12・[シート]売上!B12 ほか 2・[シート]売上 12 行目。図形・コメントは [シート]売上!D5。ヘッダー・フッターはセル番地が無く [シート]売上。Word・PowerPoint は場所ごとのまま。テキストは isText が真なら行番号だけ 12 行目) 結果の表 画面(prepareHitRow)
toLongPath path string ファイル操作に渡すパスの先頭に \\?\(ネットワークのパスは \\?\UNC\)を付け、260 文字を超えるパスも扱えるようにする。付いていればそのまま 入れ替えと書き出し インデックス作成・検索
fromLongPath path string toLongPath で付けた \\?\ を外す(Get-ChildItem の FullName から相対パスを求めるため) 同上 インデックス作成・検索
testPathUnder path, root bool path が root の下(root そのものは含まない)にあるか。..・.・最後の . や空白・\\?\ を解決してから比べる。状態のファイルから読んだ名前でフォルダを消す前に使う ファイルの読み書きの範囲 インデックス・作業フォルダの削除, IndexCatalog
trimTrailingSeparator path string パスの末尾の \・/ を落とす(ドライブのルート・\\?\ だけのパスは落とさない)。リンクの判定・削除の入口で使う 同上 testPathIsLink・removeTreeNoFollow
removeDirectoryRetry path, tries(既定 3), waitMilliseconds(既定 200) – フォルダを中身ごと削除する(removeTreeNoFollow。中のリンクは辿らない)。ほかのアプリが一時的に掴んでいることがあるため、少し待って数回試す。消したあとに [System.IO.Directory]::Exists でフォルダが残っていれば、成功にせず例外にする(呼ぶ側は、消えたことが確かめられてから記録する)。試すたびに Exists が偽なら getPathState で見る。無いと確かめられたとき・フォルダでないものが同じ名前であるときは成功にする。届かない・読めないなど有無が分からないときは、試し直さずに OS の文面を添えて例外にする(権限が無いのに「削除しました」と記録しない)。フォルダとして在るのに開けないときだけ、決めた回数まで待って試し直し、使い切れば例外にする。空のパスは何もしない ファイルの読み書きの範囲 インデックス作成・RemoveIndex・removeDroppedFolders(インデックス・作業フォルダの削除)
removeTreeNoFollow path – フォルダを中身ごと削除する。ジャンクション・シンボリックリンクは辿らず、リンクだけを外す(先は消さない)。path 自身がリンクならリンクだけを外す。先に全体を数え、リンクかどうか確かめられないフォルダ(Unknown)が 1 つでもあれば、何も消さずに例外を投げる。消す前に、フォルダごとにリンクでないかを確かめ直し、数えたあとにリンクに替わっていれば例外を投げる(それまでに消した分は戻らない。何も消さないと言えるのは、数える段で Unknown を見つけたときだけ)。確かめ直すのは、そのフォルダ自身だけで、上の階層が途中で替わったときは見つけられない。末尾の \・/ は落とす。読み取り専用の属性は外してから消し、260 文字を超えるパスも扱う。フォルダが無ければ何もしない 同上 removeDirectoryRetry
removeEntryOnly item(FileSystemInfo) – 1 つのファイル・フォルダ・リンクを、中を辿らずに消す(読み取り専用の属性は外してから)。フォルダは空のものだけ消す 同上 removeTreeNoFollow・clearTmpDir
getFilesNoFollow root, -IncludeHidden, -SkipUnknown @{ Files; Directories; Links; HasError; Reason } root の下のファイル・フォルダを、リンクのフォルダへ降りずに集める(Get-ChildItem -Recurse・AllDirectories の代わり)。ジャンクション・シンボリックリンクは Links に入れ、中へ降りない(リンクの先のファイルは Files に入らない)。root そのものはリンクかどうか見ず、先の中を集める。Hidden は、既定では除く(-IncludeHidden で含める。System だけのものは入れる)。並びは Get-ChildItem -Recurse と同じ(フォルダごとに、その中身を並べてから、サブフォルダの下へ進む)。getLinkKind が Unknown のフォルダ(OneDrive のオンデマンドのフォルダなど)は、既定では降り、-SkipUnknown を付けると降りずに Links に入れる。読めないフォルダがあっても例外にせず HasError を $true・Reason にして、読めたところを返す ファイルの読み書きの範囲 findTargetFiles・getIndexTsvFilesNoFollow
getLinkKind item(Get-Item・Get-ChildItem などが返すもの) string Link(ジャンクション・シンボリックリンク)・Unknown(フォルダで ReparsePoint が付き種類が確かめられない、属性が読めない)・Plain(それ以外)のどれか 同上 testLinkItem・removeTreeNoFollow
testLinkItem item(Get-Item・Get-ChildItem などが返すもの) bool ジャンクション・シンボリックリンクなら $true。属性の ReparsePoint が付き、LinkType が Junction・SymbolicLink のもの(getLinkKind が Link)。フォルダで ReparsePoint が付いて種類が確かめられないもの(Unknown)、属性が読めないときも $true(辿らない側に倒す)。ReparsePoint のファイル(OneDrive のオンデマンドなど)は $false 同上 testPathIsLink・removeTreeNoFollow
testPathIsLink path bool path そのもの(途中の階層は見ない)がリンクなら $true。無い・空のパスは $false。確かめられないときは $true。末尾の \ は落として調べる 同上 testPathHasLink・clearTmpDir・newWorkerTmpDir・removeEmptyDir・newDirectoryReplacingExisting
testPathHasLink base, path bool base の下から path までの各階層(base 自身は見ない)に、リンクがあれば $true。まだ無い階層から先は見ない。path が base の下になければ、確かめられないので $true 同上 initTmpDir・removeStaleTmpDirs
newDirectoryUnder path, root bool root の下に path のフォルダを(途中の階層ごと)作り、作れたら(すでにあるときも)$true。root から path までの途中(path を含む)にリンクがある・path が root の下でない・空のパスのときは、何も作らずに $false。作ったあとにもう一度確かめ、リンクに替わっていれば $false。root 自身は見ない(path が root と同じなら、root を作って $true)。作れない理由(権限など)は例外 同上 copySourceForOpen
testRemovablePath path, root bool path を root の下で消す・移す・作ってよいか。path と root が絶対パス(ドライブ・UNC)、path が root の下(testPathUnder)、root から path までの途中にリンクが無い(testPathHasLink。まだ無い階層は見ない)のすべてが成り立つときだけ $true。root そのものがリンクの構成は今までどおり動く。-leafLinkOk を付けると path そのものがリンクでもよい(途中だけ見る。removeDirectoryUnder・moveDirectoryUnder が付け、消す・移すフォルダそのものがリンクなら、リンクだけを外す・動かす)。確かめられないときは $false 同上 removeDirectoryUnder・moveDirectoryUnder・publishIndexFiles・clearOldOpenCopies
removeFileUnder path, root bool testRemovablePath が真のときだけ、ファイル 1 つを removeEntryOnly で消して $true(path 自身がリンクならリンクだけを外す。無いときも $true)。偽なら何も消さずに $false(ログ・例外は呼ぶ側) 同上 removeOldSystemIndex
removeDirectoryUnder path, root, tries(既定 3) bool testRemovablePath が真のときだけ removeDirectoryRetry で消して $true。偽なら何も消さずに $false(ログ・例外は呼ぶ側が決める)。フォルダを消す呼び出しは、これを通す(通せないものは tests/meta/remove_entry.Tests.ps1 の一覧に理由つきで置く) 同上 removeBookDir・RemoveIndex・removeOldIndexOf・removeOldSystemIndex・removeDroppedFolders・removeTmpDir・removeStaleProcessDirs・インポート・本文インデックスの TSV の削除
moveDirectoryUnder source, destination, root, sourceRoot(省略時は root) bool 移すと元の場所から無くなるため、元(sourceRoot の下)と先(root の下)の両方を testRemovablePath で確かめてから moveDirectoryRetry で移して $true。偽なら何も移さずに $false 同上 RenameIndex・renameOldIndexFolder・インポート(swapInImportedIndexDir・restoreSwappedIndexDir。元と先で根が違う)
moveDirectoryRetry source, destination, tries(既定 5), waitMilliseconds(既定 200。試すたびに倍にする) – フォルダを移動する。removeDirectoryRetry と同じ理由で、待つ時間を倍にしながら数回試す インポート インデックスのインポート(swapInImportedIndexDir・restoreSwappedIndexDir)・ワークスペースの移動(WorkspaceMover.MoveEntries)
testSameDriveRoot first, second bool 2 つのパスが同じドライブ(同じ根)にあるか。同じなら Directory.Move、違えば写してから消す。テストが別のドライブを用意せずに差し替えられるよう関数にしてある – WorkspaceMover.MoveEntry
testAnyEntry entries(EnumerateFiles などの列挙), predicate(省略可) 真偽値 条件に合うものが 1 つでもあるか。見つけたところで列挙をやめ、列挙子を必ず Dispose する(foreach を途中で抜けると下のフォルダを掴んだまま残り、そのフォルダを移動・削除できなくなるため) – 前の版のワークスペースの状態(getLegacyIndexState)・インデックスの有無(testIndexExists)・元のファイルごとのフォルダの判定(testIndexBookDir)
selectFirstEntries entries(EnumerateFileSystemEntries などの列挙), count 配列 列挙の先頭から count 件までを配列にして返す。count 件で列挙をやめ、列挙子を必ず Dispose する(testAnyEntry と同じ理由) – 作業フォルダに選べるかの判定(testDefaultWorkspace・getFolderEntrySample)

TSV の整形・ファイル名の確かめ(shared/core/text.ps1)

関数 入力 出力 概要 詳細 使用元
replaceCellNewLine inputString string " で囲まれた範囲の改行(CRLF・CR・LF)を $cellNewLine に置き換える Excel formatTsv
formatTsv content, firstRow(既定 1), firstColumn(既定 1) string TSV 整形。N 行目・k 列目をシートの N 行目・k 列目にそろえる 同上 prettyTsv
countTsvFields line int Excel に貼り付けたときのセル数(" で始まるセルは閉じる " までを 1 セルとする。先頭のセルが空でも数え落とさない) 1 行の組み立て 検索
toColumnName number string 列番号を列名に変換(1 → A、27 → AA) 同上 toResultHeader
splitTsvCells line string[] TSV の 1 行をセルに分ける(" で囲まれたセルは 1 セルとし、囲みを外す。countTsvFields と同じ区切り方。画面のプレビューは同じ区切り方を型 HitRow(ui/search/result_types.ps1)の中に持つ) – テストだけ
testTextTrimmed actualWidth, requiredWidth, tolerance bool 文字が枠に入りきらず省略(…)で切れているか(要る幅が実際の幅より誤差を超えて大きいときだけ $true。幅 0 以下は $false) 同上 addTrimmedToolTip(shared/ui/trimmed_tooltip.ps1)
toSafeFileName name string ファイル名禁止文字を全角に置換 インデックス作成 インデックス名(newIndexName・getTargetFolders)、シート名の照合(画面。元のファイルを開くとき)
getFolderNameProblemText name, allowReserved(既定 $false) string(問題の文。使えれば空) フォルダ名として使えるか(空・前後の空白・長すぎる・使えない文字・最後の .・予約名)。allowReserved が $true のときは予約名(aux.backup など)を拒まない(既にある実在のフォルダの名前を空にしないため。新しく付ける名前には使わない)。どのツールからも使う 同上 testIndexName, testStoredIndexName, newIndexName, getTargetFolders, readStatusFile
testPlainFolderName name bool 外へ出ず名前のとおりに作れるフォルダ名か(空・.・..・長すぎる・使えない文字だけを拒む。予約名・最後の . や空白は問わない) 同上 readStatusFile(LegacyFolders の判定)
formatDisplayText text, keepLineBreaks(スイッチ) string インデックスから来た文字列を画面に出すときの表示用の文字列。制御文字(C0・C1)と向きを変える文字(U+202E など。並びは $displayControlChars)を U+FFFD にする。keepLineBreaks ではタブ・改行を残す。コピー・開くには元の値を使う 元のファイルを開く newFileGroup, addFileGroupLocation, openFoundSource ほか結果の表の表示

日時の文字列は formatTime(time → string。当日なら H:mm、それ以前は M/d H:mm。$null は空。判断層の search_bar_view.ps1 と画面層が使う)も text.ps1 にある。

TSV のファイルの書き出し(shared/core/tsv_file.ps1)

関数 入力 出力 概要 詳細 使用元
prettyTsv 入力パス, 出力パス, firstRow(既定 1), firstColumn(既定 1) bool 入力(UTF-16)を読み、formatTsv して UTF-8(BOM 付き)で保存。内容が空なら保存せず $false 同上 インデックス作成

テキストファイルの読み取り(shared/core/text_file.ps1)

詳細は テキストファイルの読み取り。バイト列から判定する関数はファイルを読み書きしない(readTextFile だけがファイルに触る)。

関数 入力 出力 概要 使用元
testTextExtension path bool 拡張子が対象のテキストの拡張子($textExtensions。大文字・小文字を区別しない)か ingestFile, getContentIndexFileKind, describePlace, findTargetFiles($targetExtensions)
testTextOpenWithNotepad path bool 拡張子が、既定のアプリではなくメモ帳で開く拡張子($textNotepadExtensions。開くと実行・登録になるもの。大文字・小文字を区別しない。終わりの . と空白は Windows が無視して開くので、落としてから見る)か openFoundSource(元のファイルを開く)
detectTextEncoding bytes string / $null バイト列だけから文字コード(UTF8 / UTF16LE / UTF16BE / ShiftJIS / EUCJP / ISO2022JP)を判定する。判定できない・あいまいなものは $null(取り込まない) readTextFile
detectJapaneseUtf16WithoutNul bytes string / $null NUL の無い BOM 無し UTF-16(日本語だけの文章)を、かなの割合と日本語の文章に出る文字の割合で判定する(UTF16LE / UTF16BE) detectTextEncoding
getIso2022JpVerdict bytes string ISO-2022-JP かの判定(yes / broken(ESC $ B があるが 8 ビット・規格外の ESC がある)/ none) detectTextEncoding
detectLegacyJapaneseEncoding bytes string / $null UTF-8 として読めなかったバイト列が Shift_JIS か EUC-JP か。決まらなければ $null detectTextEncoding
testHalfWidthKanaNatural text bool 半角カナの多い文字列が、濁点・半濁点の位置など半角カナの並びとして自然か detectLegacyJapaneseEncoding
tryDecodeStrict bytes, codePage string / $null 読めないバイト列があれば $null、読めれば文字列 detectTextEncoding
testTextPlausible text bool 制御文字・私用領域・U+FFFD を含まない(テキストとして自然)か detectLegacyJapaneseEncoding
decodeTextBytes bytes, encodingName string detectTextEncoding が返した文字コードで、バイト列を文字列にする(BOM は取り除く) readTextFile
splitTextLines text string[] StreamReader.ReadLine と同じ分け方(CRLF・LF・CR)で行に分ける。途中の空の行は残し、行末の空白は取り除き、末尾の空の行は捨てる readTextFile
readTextFile path, maxBytes(既定 $textFileMaxBytes) string[] ファイルを読み取り専用の共有で開き、大きさの上限・文字コードを確かめてから行の並びにする。上限超え・バイナリは例外(エラーメッセージ一覧) extractTextFile

インデックスへの配置(tebunko/index/index_store.ps1)

関数 入力 出力 概要 詳細 使用元
getIndexTsvCounts dir(既定 $workspace.IndexDir) 相対パス → 数の辞書 / $null インデックスの中のファイルを 1 回列挙して数える。本文インデックスのファイルはそのファイルの相対パス → 1(0 バイトなら -1)、本文インデックスに入れる前の TSV は元のファイルのフォルダの相対パス(取り込み一覧の相対パスと同じ)→ TSV の数(0 バイトの TSV があれば -1。TSV の無いフォルダは 0)。列挙できなければ $null 取り込み対象の決定 インデックス作成(取り込み対象の決定)
testIndexComplete row, relPath, counts bool 取り込み一覧の「済」の行に対して、インデックスがそろっているかを返す。そのフォルダ・その拡張子の本文インデックスのファイルがあれば(0 バイトでなければ)$true。無ければ本文インデックスに入れる前の TSV を見て、行の TSV 数より少ない・0 バイトなら $false(取り込み直す)。TSV 数が空・counts が $null のときは確認しない 同上 インデックス作成(取り込み対象の決定)
publishIndexFiles fromDir, bookDir, stagingDir, indexRoot, publishRoot – 書き出した TSV を stagingDir に集めてから、bookDir をフォルダごと入れ替える(作りかけのインデックスを残さない)。別ドライブでフォルダごと移せない場合は 1 件ずつ移す 入れ替えと書き出し インデックス作成(publishTsv)

本文インデックスの形式(tebunko/index/content_index_format.ps1)

形式は インデックスのファイルの形「本文インデックスの形式」。判断層のため、ファイルを読み書きしない。

関数 入力 出力 概要 使用元
getContentIndexFileKind book string 元のファイル名から種類(Excel / Word / PowerPoint / テキスト / PDF。分からなければ空) convertBookToContentIndexBlock, convertPlaceToContentIndexMeta, describePlace, toResultLine, addFileGroupLocation・ensureRows(getPlace に渡す値・ファイルの見出しの AppKind・検索結果の行の IsExcel), testCellPrefixedPlace, searchContentIndexFiles(長い行を切るかの判定), readContentIndexLines
getContentIndexExtension / getContentIndexFileName / readContentIndexFileName book / extension, part / name string / @{Extension; Part} 本文インデックスを分ける拡張子(小文字・. なし) / 本文インデックスのファイルの名前(content_index.<拡張子>.<番号>.tsv) / 名前から拡張子と番号を取り出す convertFolderToContentIndex, getIndexTsvCounts
splitContentIndexBooksByExtension books [ordered] 拡張子 → 並び 元のファイルの並びを拡張子ごとに分ける(各並びの中の順は変えない) convertFolderToContentIndex
encodeContentIndexValue / decodeContentIndexValue value string メタ情報の値の制御文字(タブを除く)と % を %XX にする / 戻す convertToContentIndexText, readContentIndexPlaces
convertPlaceToContentIndexMeta book, place [ordered] キー → 値 場所の名前(TSV のファイル名。見積[図形]・見積[ヘッダー・フッター]・ページ001 など)を場所のメタ情報にする。組み立て直して同じ名前にならないものは 部分=<名前>・対象=本文 convertToContentIndexText
convertContentIndexMetaToPlace meta string 場所のメタ情報から場所の名前を組み立てる(画面の表示・図形とコメントの除外・元のファイルを開く処理が使う形) readContentIndexPlaces
convertToContentIndexBody text string TSV の中身を本文インデックスに入れる形にする(改行を LF に、末尾に LF、U+001C〜U+001F を除く) convertToContentIndexText
convertToContentIndexText books string 元のファイルの並び(TSV から新しく作るもの、または前の本文インデックスから写すまとまり)から、本文インデックスの文字列を作る convertFolderToContentIndex
readContentIndexPlaces text @{Book; Location; CellPrefixed; Start; End} の並び 本文インデックスの文字列から、場所ごとの元のファイル名・場所の名前・行の先頭がセル番地か(CellPrefixed。Excel の図形・コメントが $true。testContentIndexCellPrefixed)・中身の範囲を先頭から順に返す。版が違えば例外 検索(searchContentIndexFiles)、readContentIndexLines
testContentIndexCellPrefixed book, meta bool 場所の行が「セル番地 + タブ + 文字」の形か。メタ情報の 対象 を testCellPrefixedPlace に渡して返す readContentIndexPlaces
testCellPrefixedPlace book, kind bool 場所の行が「セル番地 + タブ + 文字」の形か(元のファイルが Excel で、場所の種類が図形・コメント。ふつうの場所の種類は空)。この判定はここだけにあり、検索結果の行(HitRow.IsCellPrefixed)も行を作るときにこれで決める testContentIndexCellPrefixed、検索結果の行を作る所(result_list.ps1)
splitContentIndexTextByBook text @{Name; Block} の並び 本文インデックスの文字列を元のファイルごとのまとまりに分ける(入れ替えない元のファイルをそのまま写すため)。版が違えば例外 convertFolderToContentIndex
getContentIndexBodyText text string メタ情報の行を除いた中身(2-gram の値を作るため) getFileGramValues

インデックスの格納形式の目録(tebunko/index/content_index_format.ps1・index_format_store.ps1)

形式は インデックスのファイルの形「置き場と目録」。判定は判断層(getIndexFormatState)、ファイルの読み書きは状態層(index_format_store.ps1)。

関数 入力 出力 概要 使用元
getIndexFormatState catalog, oldNames, v2Names, hasLegacyIndex @{State; Message; Indexes} 目録の行と、古い置き場・今の置き場にあるインデックスの名前から、ワークスペースと各インデックスの状態(Current・Building・Rebuilding・Old・Empty・Broken・Newer)・検索に出すか・文言を決める。ファイルには触れない getWorkspaceIndexFormat
testContentIndexVersionLine line bool 本文インデックスの先頭行が今の版の 版= の行か testIndexFileCurrentVersion
readIndexFormat / writeIndexFormat path / indexes, path, appVersion @{Status; Version; AppVersion; Indexes} / なし 目録を読む(Ok・Missing・Broken・Newer・Older)/ 一時ファイルに書いて入れ替える getWorkspaceIndexFormat, updateIndexFormat
updateIndexFormat change, path bool 目録を排他で読み、change で書き換えて書く。今より新しい版は書き換えない setIndexFormatRow, removeIndexFormatRow, renameIndexFormatRow, markIndexFormatBuilding, completeIndexFormat
setIndexFormatRow / removeIndexFormatRow / renameIndexFormatRow name, state / name / oldName, newName bool インデックス 1 つの行を書く / 消す / 名前を変える index_store.ps1, index_catalog.ps1
repairIndexFormat workspace 目録の読み取り結果 目録が壊れたとき、今の版の本文インデックスのファイルがあるインデックスを「作成中」として書き直す getWorkspaceIndexFormat
getWorkspaceIndexFormat workspace getIndexFormatState の結果 今のファイルから、ワークスペースと各インデックスの状態を求める(目録が壊れていれば先に直す) indexer_run.ps1, index_detail.ps1, index_list.ps1
findOldIndexNames / getIndexNamesWithContent workspace / dir 名前の並び 古い置き場・今の置き場で本文インデックスを持つインデックスの名前 getWorkspaceIndexFormat
markIndexFormatBuilding names, workspace bool この回で作るインデックスのうち目録に行が無いものを「作成中」で足す invokeIndexerBody
completeIndexFormat names, workspace @{Updated; Failed} 作り終えたインデックスの行を「作り終えた」にし、古い置き場の分を消す invokeIndexerBody
removeOldIndexOf name, workspace @{Removed; Failed} 古い置き場の <名前> と、空になった古い置き場(content_index\・古い ingest_status.tsv)を消す。名前が不正なら何も消さない。ジャンクションは辿らない completeIndexFormat

本文インデックスの読み書き(tebunko/index/content_index_store.ps1)

関数 入力 出力 概要 詳細 使用元
writeContentIndexFile / readContentIndexText path, text / path – / string 本文インデックスのファイルを UTF-16LE(BOM 付き)で書く(<名前>.tmp に書いてから File.Replace で置き換える) / 読む(置き換え・削除を妨げない共有モード) インデックスのファイルの形 convertFolderToContentIndex, readContentIndexLines
getIndexFolderBooks folder @{Name; Places} の並び フォルダ直下の元のファイルごとのフォルダ(<ファイル名.xlsx>\<場所>.tsv)から、本文インデックスに入れる元のファイルと場所の並びを作る(ファイル名は convertIndexFileNameToPlace で場所に戻す。並びは前の版と同じになるよう、戻した場所を符号化し直したキーで並べ替える) 同上 convertFolderToContentIndex
convertFolderToContentIndex folder, destFolder, removeBooks, removeTsv @{Books; Tsv; Chars; Files; Texts} フォルダ 1 つの TSV から拡張子ごとの本文インデックスのファイルを書く。前の本文インデックスのファイルとまぜ(TSV のある元のファイルは入れ替え、removeBooks は外し、ほかは写す)、元のファイルが無くなった拡張子の本文インデックスのファイルは消す。removeTsv なら書き終えた後に TSV のフォルダを消す。Texts は書いた中身 同上 updateFolderContentIndex
updateFolderContentIndex folder, removeBooks 同上 convertFolderToContentIndex を同じフォルダに書き、TSV を消す形で呼ぶ 同上 publishIndexFolders
findContentIndexFiles root, relPath, recurse @{Path; Root; RelDir; RelPath; Ticks; Size} の配列 フォルダ以下の本文インデックスのファイルを列挙し、フォルダの順・フォルダの中は名前の順に並べる(Path は \\?\ 付き。Ticks・Size は読んだ内容を使い回してよいかの判定に使う) 検索を速くする仕組み getContentIndexFiles
findIndexFoldersWithBooks root string[] 元のファイルごとのフォルダ(本文インデックスに入れる前の TSV)が直下にあるフォルダを返す(インデックス作成が途中で止まったとき) インデックスのファイルの形 インデックス作成(開始時)
publishIndexFolders pending(フォルダ → 無くなった元のファイル名), indexRoot @{ Count(書き出したフォルダの数); Skipped(飛ばしたフォルダの@{ Rel; Stage; Reason }); Published(本文インデックスのファイルを書き終えたフォルダ)} フォルダごとに、本文インデックスに書き(updateFolderContentIndex)、TSV を消し。フォルダの 1 つが失敗しても例外にせず、そのフォルダを飛ばして残りを続け、ログに黄色で出す(本文インデックスを書き終える前なら何も書き換えない) 同上 インデックス作成(indexer_run.ps1 の flushPending)
readContentIndexLines path, book, location, firstLine, count, cache, marks @{Rows; End; Marks} 本文インデックスのファイルの中の元のファイル book・場所 location の firstLine 行目から count 行を返す(行の数え方は検索と同じ。Rows は @{LineNumber; Line} の並び。End は count 行に満たなかった=その先にもう行が無い)。cache(newTsvTextCache)に同じ本文インデックスのファイルの内容があれば読み直さない。無ければ、marks(前に読んだときの控え。ファイルのパス・更新日時・サイズ・場所の一覧・場所ごとの 200 行ごとの文字の位置)が今のファイルのものである間は、場所の一覧を使い回し、控えのうち目当てに一番近い所から必要な行までだけを読む(readContentIndexRange)。marks が無い・別のファイルのもの・更新日時かサイズが違うとき、範囲を読めないとき、読んでいる間にファイルが置き換わったときは、ファイルの全体を読む(初めて開くファイルの最初の読みはこれに当たる)。更新した控えを Marks で返す(引数で渡し戻り値で受ける。複数のスレッドで動くため $script: に持たない。渡された控えは書き換えない)。更新日時もサイズも同じまま中身だけが書き換わったファイルは、控えが古いことを見分けられない。読めない・見つからなければ空 選択行のプレビュー 画面
readContentIndexRange path, start, end, firstLine, lines, baseLine(既定 1), checkpoints string / null 本文インデックスのファイル(UTF-16LE・BOM 付き)の、文字の位置 start(含む)から end(含まない)までを start から数え、firstLine 行目の先頭から lines 個目の改行までを文字列で返す(それより前の行は持たない)。baseLine は start の行の番号。checkpoints(ハッシュテーブル)を渡すと、通った 200 行ごとの行の先頭(行の番号 → 文字の位置)を足す。BOM が無ければ $null(呼び出し側がファイルの全体を読む)。置き換え・削除を妨げない共有モードで開く 同上 readContentIndexLines