package main import ( "clive/cmd" "clive/sre" "clive/zx" "fmt" "html" "io" "strconv" "strings" ) const ( CSS = `//lsub.org/ls/class.css` // CSS used for html output MAN = `//lsub.org/sys/man` // base url for man pages in output TEMPLATE = `/zx/usr/web/sys/man/TEMPLATE` // template for clive man pages ) var cliveMan bool var sect string struct htmlFmt { lvl int ps int fnts []int *par outfig string ups bool // hacks for clive man hasSeeAlso bool // hacks for clive man } func escHtml(s string) string { ns := "" noesc := false w := "" for _, r := range s { switch { case r == 1: noesc = true if w != "" { ns += html.EscapeString(w) w = "" } continue case r == 2: noesc = false continue case noesc: ns += string(r) default: w += string(r) } } if w != "" { ns += html.EscapeString(w) } return ns } func (f *htmlFmt) citeMan(cite string) bool { rg, _ := sre.Match(mrexp, cite) if len(rg) < 3 { return false } pg := rg[1] sec := rg[2] f.printParCmd(`` + cite + ``) return true } func (f *htmlFmt) wrText(e *Elem) { if e == nil { return } switch e.Kind { case Kchap, Khdr1, Khdr2, Khdr3, Kfoot: default: if e.Nb != "" { f.printPar(e.Nb, " ") } } switch e.Kind { case Kit, Kbf, Ktt, Kitend, Kbfend, Kttend: f.wrFnt(e) case Kfont: f.fntSz(e.Data) case Kurl: toks := strings.SplitN(e.Data, "|", 2) x := e.Data if f.ups { x = strings.ToUpper(x) } if len(toks) == 1 { f.printParCmd(``, x, "") } else { f.printParCmd(``, html.EscapeString(toks[0]), "") } return case Kcite: if f.citeMan(e.Data) { return } e.Data = "[" + e.Data + "]" case Kbib: nbs := strings.Split(e.Data, ",") if len(nbs) == 0 { nbs = append(nbs, "XXX") } f.printParCmd(`[`, nbs[0], ``) for _, nb := range nbs[1:] { f.printParCmd(`,`, nb, ``) } f.printParCmd("]") return case Kcref: f.printParCmd(``, e.Data, ``) return case Keref: f.printParCmd(``, e.Data, ``) return case Ktref: f.printParCmd(``, e.Data, ``) return case Kfref: f.printParCmd(``, e.Data, ``) return case Ksref: nb := strings.Replace(e.Data, ".", "x", -1) f.printParCmd(``, e.Data, ``) return case Knref: f.printParCmd(``, footRef(e.Data), ``) return } x := e.Data if f.ups { x = strings.ToUpper(x) } f.printPar(x) for _, c := range e.Textchild { f.wrText(c) } } var hfnts = map[Kind]string{ Kit: `em`, Kbf: `b`, Ktt: `code`, Kitend: "/em", Kbfend: "/b", Kttend: "/code", } var hhdrs = map[Kind]string{ Kchap: "h1", Khdr1: "h2", Khdr2: "h3", Khdr3: "h3", } var hlst = map[Kind]string{ Kitemize: "ul", Kenumeration: "ol", Kdescription: "dl", } func (f *htmlFmt) wrFnt(e *Elem) { if e.Inline { f.printParCmd("<", hfnts[e.Kind], ">") } else { f.printCmd("<%s>\n", hfnts[e.Kind]) } } var hszs = map[int]string{ -5: "tiny", -4: "tiny", -3: "scriptsize", -2: "footnotesize", -1: "small", 0: "normalsize", 1: "large", 2: "Large", 3: "LARGE", 4: "huge", 5: "Huge", } func (f *htmlFmt) fntSz(d string) { if len(d) == 0 { return } n, _ := strconv.Atoi(d) f.fnts = append(f.fnts, n) nf := len(f.fnts) if nf > 1 && f.fnts[nf-1] == -f.fnts[nf-2] { // close a font size if n < 0 { f.printParCmd(``) } else { f.printParCmd(``) } f.fnts = f.fnts[:nf-2] return } // open a font size if n > 0 { f.printParCmd(``) } else { f.printParCmd(``) } f.fnts = append(f.fnts, n) } func (f *htmlFmt) wrCaption(e *Elem) { if e.Caption == nil { f.printCmd("%s %s.", labels[e.Kind], e.Nb) } else { f.printCmd("%s %s: ", labels[e.Kind], e.Nb) f.wrText(e.Caption) f.printParCmd(``) } } func (f *htmlFmt) wrElems(els ...*Elem) { pref := strings.Repeat(f.tab, f.lvl) f.lvl++ defer func() { f.lvl-- }() for _, e := range els { f.i0, f.in = pref, pref switch e.Kind { case Kit, Kbf, Ktt, Kitend, Kbfend, Kttend: f.wrFnt(e) case Kfont: f.fntSz(e.Data) case Kcop: cop = e.Data case Kchap, Khdr1, Khdr2, Khdr3: f.closePar() f.printParCmd(``) f.printParCmd("<" + hhdrs[e.Kind] + ">") if e.Nb != "" && !cliveMan { f.printPar(e.Nb, ".") f.printPar(" ") } f.ups = cliveMan f.hasSeeAlso = false if f.ups && strings.ToLower(e.Data) == "see also" { f.hasSeeAlso = true } f.wrText(e) f.ups = false f.printParCmd("" + hhdrs[e.Kind] + ">") f.closePar() case Kpar: f.printCmd("
\n")
case Kbr:
f.printParCmd(`
`)
f.closePar()
case Kindent:
// If it contains just a fig, pic, grap, or tbl, then
// skip this level and jump to the child
if len(e.Child) == 1 || len(e.Child) == 2 && e.Child[1].Kind == Kpar {
switch e.Child[0].Kind {
case Kfig, Kpic, Keqn, Ktbl, Kgrap, Kcode:
f.wrElems(e.Child...)
continue
}
}
f.printCmd(pref + `
` + "\n") case Kitemize, Kenumeration, Kdescription: f.printCmd(pref+"<%s>\n", hlst[e.Kind]) f.wrElems(e.Child...) f.printCmd(pref+"%s>\n", hlst[e.Kind]) case Kname: f.closePar() f.printParCmd(`
`)
if e.Kind == Kverb && e.Tag != "" {
f.printCmd("[%s]:
", e.Tag)
}
f.printCmd(`` + "\n")
e.Data = indentVerb(e.Data, f.i0, f.tab)
f.printCmd("%s", html.EscapeString(e.Data))
f.printCmd(pref + `` + "\n")
case Kfoot:
// TODO: record footnote text and place a list at the end,
// like we do for bib.
case Ktext, Kurl, Kbib, Kcref, Keref, Ktref, Kfref, Ksref, Kcite:
f.wrText(e)
case Kfig:
f.printCmd(pref + "\n") f.printCmd(pref + "
\n") case Kcode: f.printCmd(pref + "
\n") f.printCmd(pref + "
` + "\n")
e.Data = indentVerb(e.Data, f.i0, f.tab)
f.printCmd("%s", html.EscapeString(e.Data))
f.printCmd(pref + `` + "\n")
f.wrCaption(e)
f.printCmd(pref + "\n") case Kpic, Kgrap, Keqn: f.printCmd(pref + "
\n") f.printCmd(pref + "
\n") case Ktbl: f.printCmd(pref + "
\n") f.printCmd(pref + "
\n") } } f.closePar() } func (f *htmlFmt) wrTbl(rows [][]string) { if len(rows) < 2 || len(rows[0]) < 2 || len(rows[1]) < 2 { return } f.printCmd("
| %s | \n", s) } else { f.printCmd("%s | \n", s) } } f.printCmd("
\n") r := "References" if eflag { r = "Referencias" } if !cliveMan { f.printCmd("
") f.closePar() } f.printCmd("
\n") } func (f *htmlFmt) wrFoots(t *Text) { foots := t.refs[Kfoot] if len(foots) == 0 { return } f.printCmd("
") f.closePar() } f.printCmd("
\n") } func (f *htmlFmt) run(t *Text) { els := t.Elems if cliveMan { if sect != "doc" { f.printCmd(`User's manual.` + "\n") f.printCmd(`Section ` + sect + `.` + "\n") } } else { f.printCmd(`
`) if len(els) > 0 && els[0].Kind == Ktitle { s := html.EscapeString(els[0].Data) f.printCmd("\n\n") f.wrElems(els...) f.wrFoots(t) f.wrBib(t.bibrefs) f.printCmd("
\n
\n\n") if !cliveMan { if cop != "" { f.printCmd("
(c) " + cop + "\n
\n")
}
f.printCmd("