132 lines
5.3 KiB
Python
132 lines
5.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""건설품셈 기계설비 제7~13장 md 읽기 (build_소요량_건설품셈_기계설비.py 가 씀).
|
|
|
|
항(###) · 목(####) · 표 · 표 머리 깊이(주석) · 표 앞 글 · [주] [비고] [계산예] 글을 읽음.
|
|
"""
|
|
|
|
import re
|
|
|
|
from _md표_읽기 import unesc
|
|
from _토목_읽기 import ROOT
|
|
|
|
BASE = ROOT / "resources/knowledge/original/원가계산/건설공사_표준품셈/본문/04_기계설비부문"
|
|
DIV = "건설품셈 기계설비 "
|
|
NOTE0 = re.compile(r"^[①-⑳]")
|
|
BLOCK = re.compile(r"^\[(주|비고|계산예|참고|참고자료|별표)\]\s*(.*)$")
|
|
|
|
|
|
class Tab:
|
|
def __init__(self, ident, title, mok, base, rows, k, hdr, pre):
|
|
self.ident, self.title, self.mok, self.base = ident, title, mok, base
|
|
self.rows, self.k, self.hdr, self.pre = rows, k, hdr, pre
|
|
self.notes: list[str] = []
|
|
|
|
|
|
def cells(line):
|
|
return [c.strip() for c in line.strip().strip("|").split("|")]
|
|
|
|
|
|
def title_of(s):
|
|
return re.sub(r"\s*\((?:['‘’]\d\d[^)]*)\)\s*$", "", s).strip()
|
|
|
|
|
|
def clean(ln):
|
|
ln = re.sub(r"<!--.*?-->", "", ln).rstrip()
|
|
return re.sub(r"^>\s?", "", ln)
|
|
|
|
|
|
def read_chapter(chdir):
|
|
"""장 폴더 → 표 목록 (표마다 항 · 목 · 기준 · 머리 깊이 · 앞 글 · 주)."""
|
|
tabs = []
|
|
for p in sorted(next(BASE.glob(chdir + "*")).glob("*.md")):
|
|
L = p.read_text(encoding="utf-8").split("\n")
|
|
L = L[[i for i, x in enumerate(L) if x.strip() == "---"][1] + 1 :]
|
|
ident = title = mok = base = ""
|
|
pre: list[str] = []
|
|
k, mode, i = 0, "", 0
|
|
while i < len(L):
|
|
raw = L[i]
|
|
ln = clean(raw)
|
|
m = re.match(r"^(#{2,4})\s+(.*)$", ln)
|
|
if m:
|
|
mode, base, pre = "", "", []
|
|
d = len(m.group(1))
|
|
if d == 2:
|
|
mm = re.match(r"^(\d+-\d+)\s+(.*)$", m.group(2))
|
|
ident, title, mok, k = mm.group(1), title_of(mm.group(2)), "", 0
|
|
elif d == 3:
|
|
mm = re.match(r"^(\d+-\d+-\d+)\s+(.*)$", m.group(2))
|
|
ident, title, mok, k = mm.group(1), title_of(mm.group(2)), "", 0
|
|
elif d == 4:
|
|
mk = re.match(r"^(?:\d+|[가-힣])\.\s*(.*)$", m.group(2))
|
|
mok = title_of(mk.group(1) if mk else m.group(2))
|
|
i += 1
|
|
continue
|
|
if not ident:
|
|
i += 1
|
|
continue
|
|
if ln.startswith("|"):
|
|
j, rows = i, []
|
|
while j < len(L) and L[j].startswith("|"):
|
|
c = cells(L[j])
|
|
if not all(re.fullmatch(r":?-+:?", x) for x in c):
|
|
rows.append(c)
|
|
j += 1
|
|
hint = ""
|
|
while j < len(L) and (L[j].startswith("<!--") or not L[j].strip()):
|
|
hint += L[j] if L[j].startswith("<!--") else ""
|
|
if not L[j].strip() and not (j + 1 < len(L) and L[j + 1].startswith("<!--")):
|
|
break
|
|
j += 1
|
|
mh = re.search(r"몸 (\d+)행까지 머리", hint)
|
|
b = base[1:-1] if base else ""
|
|
tabs.append(
|
|
Tab(ident, title, mok, b, rows, k, 1 + int(mh.group(1)) if mh else 1, pre)
|
|
)
|
|
k += 1
|
|
base, pre, mode = "", [], ""
|
|
i = j
|
|
continue
|
|
s = ln.strip()
|
|
i += 1
|
|
if not s or s.startswith("!["):
|
|
continue
|
|
mb = BLOCK.match(s)
|
|
if mb:
|
|
kind, rest = mb.groups()
|
|
mode_before = mode
|
|
mode = "note" if kind in ("주", "계산예", "비고") else ""
|
|
if kind in ("참고", "참고자료", "별표"):
|
|
if "참조" in rest and tabs and tabs[-1].ident == ident:
|
|
mode = mode_before # 딴 곳을 가리키는 글 = 앞 주 이어짐
|
|
tabs[-1].notes.append(unesc(f"{kind} {rest}"))
|
|
continue
|
|
pre = [s] if not rest else [f"[{kind}] {rest}"]
|
|
mode = ""
|
|
continue
|
|
first = rest if kind == "주" else f"{kind} {rest}".strip()
|
|
if first and tabs and tabs[-1].ident == ident:
|
|
tabs[-1].notes.append(unesc(first))
|
|
mode = "note" if kind in ("주", "계산예") else ""
|
|
if kind == "계산예":
|
|
mode = "calc"
|
|
continue
|
|
if re.fullmatch(r"\(.*\)", s) and not s.startswith("(주"):
|
|
base, mode = s, ""
|
|
continue
|
|
if mode in ("note", "calc") and tabs and tabs[-1].ident == ident:
|
|
t = tabs[-1]
|
|
if mode == "calc":
|
|
t.notes.append("계산예 " + unesc(s)) if not t.notes or not t.notes[
|
|
-1
|
|
].startswith("계산예") else t.notes.__setitem__(
|
|
-1, t.notes[-1] + " " + unesc(s)
|
|
)
|
|
elif NOTE0.match(s) or not t.notes:
|
|
t.notes.append(unesc(s))
|
|
else:
|
|
t.notes[-1] += " " + unesc(s)
|
|
else:
|
|
pre.append(s)
|
|
return tabs
|