git.sophuwu.com > manweb   
              93
            
             package manpage

import (
	"fmt"
	"git.sophuwu.com/manweb/CFG"
	"git.sophuwu.com/manweb/embeds"
	"git.sophuwu.com/manweb/neterr"
	"git.sophuwu.com/manweb/stats"
	"net/http"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
)

type ManPage struct {
	Name    string
	Section string
	Path    string
}

func (m *ManPage) Url() string {
	if m.Section != "" && m.Name != "" {
		return fmt.Sprintf("%s.%s", m.Name, m.Section)
	}
	return ""
}

func (m *ManPage) Title() string {
	if m.Section != "" && m.Name != "" {
		return fmt.Sprintf("man %s.%s", m.Name, m.Section)
	}
	return ""
}

func ext(s string) (string, string) {
	if n := filepath.Ext(s); n != "" {
		return s[:len(s)-len(n)], n[1:]
	}
	return s, ""
}

var ManDotName = regexp.MustCompile(`^[^ ]+?(\.[0-9]+[a-z]*)?$`)

func (m *ManPage) Find(q string) bool {
	if !ManDotName.MatchString(q) {
		return false
	}
	args := []string{"--where", q}
	if strings.Contains(q, ".") {
		m.Name, m.Section = ext(q)
		args = []string{"-s" + m.Section, "--where", m.Name}
	}
	b, err := exec.Command(CFG.ManCmd, args...).Output()
	if err != nil {
		return false
	}
	m.Path = strings.TrimSpace(string(b))
	m.Name = filepath.Base(m.Path)
	m.Name, m.Section = ext(m.Name)
	if m.Section == "gz" {
		m.Name, m.Section = ext(m.Name)
	}
	return !(m.Section == "" || m.Name == "" || m.Path == "")
}

var LinkRemover = regexp.MustCompile(`(<a [^>]*>)|(</a>)`).ReplaceAllString
var HTMLManName = regexp.MustCompile(`(?:<b>)?([a-zA-Z0-9_.:\-]+)(?:</b>)?\(([0-9][0-9a-z]*)\)`)
var htmlRep = `<a href="?$1.$2">$1($2)</a>`

func (m *ManPage) Html() (string, neterr.NetErr) {
	b, err := exec.Command(CFG.Mandoc, "-Thtml", "-O", "fragment", m.Path).Output()
	if err != nil {
		return "", neterr.Err500
	}
	html := LinkRemover(string(b), "")
	html = HTMLManName.ReplaceAllString(html, htmlRep)
	return html, nil
}

func Http(w http.ResponseWriter, r *http.Request, q string) bool {
	var m ManPage
	if !m.Find(q) {
		return false
	}
	html, err := m.Html()
	if embeds.ChkWriteError(w, r, err, q) {
		return true
	}
	embeds.WriteHtml(w, r, m.Title(), html, m.Url(), m.Url())
	stats.Count(m.Url())
	return true
}