docs: document job type

docs-types
sammyette 2023-01-07 12:35:06 -04:00
parent 07a7a75b46
commit a4dea1aefd
Signed by: sammyette
GPG Key ID: 904FC49417B44DCD
6 changed files with 174 additions and 29 deletions

View File

@ -7,6 +7,7 @@ import (
"go/doc" "go/doc"
"go/parser" "go/parser"
"go/token" "go/token"
"regexp"
"strings" "strings"
"os" "os"
"sync" "sync"
@ -31,6 +32,7 @@ type emmyPiece struct {
} }
type module struct { type module struct {
Types []docPiece
Docs []docPiece Docs []docPiece
Fields []docPiece Fields []docPiece
Properties []docPiece Properties []docPiece
@ -38,6 +40,7 @@ type module struct {
Description string Description string
ParentModule string ParentModule string
HasInterfaces bool HasInterfaces bool
HasTypes bool
} }
type docPiece struct { type docPiece struct {
@ -49,6 +52,7 @@ type docPiece struct {
GoFuncName string GoFuncName string
IsInterface bool IsInterface bool
IsMember bool IsMember bool
IsType bool
Fields []docPiece Fields []docPiece
Properties []docPiece Properties []docPiece
} }
@ -119,6 +123,69 @@ func docPieceTag(tagName string, tags map[string][]tag) []docPiece {
return dps return dps
} }
func setupDocType(mod string, typ *doc.Type) *docPiece {
docs := strings.TrimSpace(typ.Doc)
inInterface := strings.HasPrefix(docs, "#interface")
if !inInterface {
return nil
}
tags, doc := getTagsAndDocs(docs)
var interfaces string
typeName := strings.ToUpper(string(typ.Name[0])) + typ.Name[1:]
typeDoc := []string{}
if inInterface {
interfaces = tags["interface"][0].id
}
fields := docPieceTag("field", tags)
properties := docPieceTag("property", tags)
for _, d := range doc {
if strings.HasPrefix(d, "---") {
// TODO: document types in lua
/*
emmyLine := strings.TrimSpace(strings.TrimPrefix(d, "---"))
emmyLinePieces := strings.Split(emmyLine, " ")
emmyType := emmyLinePieces[0]
if emmyType == "@param" {
em.Params = append(em.Params, emmyLinePieces[1])
}
if emmyType == "@vararg" {
em.Params = append(em.Params, "...") // add vararg
}
em.Annotations = append(em.Annotations, d)
*/
} else {
typeDoc = append(typeDoc, d)
}
}
var isMember bool
if tags["member"] != nil {
isMember = true
}
var parentMod string
if inInterface {
parentMod = mod
}
dps := &docPiece{
Doc: typeDoc,
FuncName: typeName,
Interfacing: interfaces,
IsInterface: inInterface,
IsMember: isMember,
IsType: true,
ParentModule: parentMod,
Fields: fields,
Properties: properties,
}
return dps
}
func setupDoc(mod string, fun *doc.Func) *docPiece { func setupDoc(mod string, fun *doc.Func) *docPiece {
docs := strings.TrimSpace(fun.Doc) docs := strings.TrimSpace(fun.Doc)
inInterface := strings.HasPrefix(docs, "#interface") inInterface := strings.HasPrefix(docs, "#interface")
@ -220,6 +287,7 @@ func main() {
for l, f := range pkgs { for l, f := range pkgs {
p := doc.New(f, "./", doc.AllDecls) p := doc.New(f, "./", doc.AllDecls)
pieces := []docPiece{} pieces := []docPiece{}
typePieces := []docPiece{}
mod := l mod := l
if mod == "main" { if mod == "main" {
mod = "hilbish" mod = "hilbish"
@ -237,6 +305,14 @@ func main() {
} }
} }
for _, t := range p.Types { for _, t := range p.Types {
typePiece := setupDocType(mod, t)
if typePiece != nil {
typePieces = append(typePieces, *typePiece)
if typePiece.IsInterface {
hasInterfaces = true
}
}
for _, m := range t.Methods { for _, m := range t.Methods {
piece := setupDoc(mod, m) piece := setupDoc(mod, m)
if piece == nil { if piece == nil {
@ -254,6 +330,7 @@ func main() {
shortDesc := descParts[0] shortDesc := descParts[0]
desc := descParts[1:] desc := descParts[1:]
filteredPieces := []docPiece{} filteredPieces := []docPiece{}
filteredTypePieces := []docPiece{}
for _, piece := range pieces { for _, piece := range pieces {
if !piece.IsInterface { if !piece.IsInterface {
filteredPieces = append(filteredPieces, piece) filteredPieces = append(filteredPieces, piece)
@ -276,10 +353,28 @@ func main() {
interfaceModules[modname].Properties = piece.Properties interfaceModules[modname].Properties = piece.Properties
continue continue
} }
interfaceModules[modname].Docs = append(interfaceModules[modname].Docs, piece) interfaceModules[modname].Docs = append(interfaceModules[modname].Docs, piece)
} }
for _, piece := range typePieces {
if !piece.IsInterface {
filteredTypePieces = append(filteredTypePieces, piece)
continue
}
modname := piece.ParentModule + "." + piece.Interfacing
if interfaceModules[modname] == nil {
interfaceModules[modname] = &module{
ParentModule: piece.ParentModule,
}
}
interfaceModules[modname].Types = append(interfaceModules[modname].Types, piece)
}
docs[mod] = module{ docs[mod] = module{
Types: filteredTypePieces,
Docs: filteredPieces, Docs: filteredPieces,
ShortDescription: shortDesc, ShortDescription: shortDesc,
Description: strings.Join(desc, "\n"), Description: strings.Join(desc, "\n"),
@ -335,17 +430,46 @@ func main() {
} }
f.WriteString("\n") f.WriteString("\n")
} }
if len(modu.Docs) != 0 { if len(modu.Types) != 0 {
f.WriteString("## Functions\n") f.WriteString("## Types\n")
} for _, dps := range modu.Types {
for _, dps := range modu.Docs { f.WriteString(fmt.Sprintf("### %s\n", dps.FuncName))
f.WriteString(fmt.Sprintf("### %s\n", dps.FuncSig)) for _, doc := range dps.Doc {
for _, doc := range dps.Doc { if !strings.HasPrefix(doc, "---") {
if !strings.HasPrefix(doc, "---") { f.WriteString(doc + "\n")
f.WriteString(doc + "\n") }
} }
if len(dps.Properties) != 0 {
f.WriteString("#### Properties\n")
for _, dps := range dps.Properties {
f.WriteString(fmt.Sprintf("- `%s`: ", dps.FuncName))
f.WriteString(strings.Join(dps.Doc, " "))
f.WriteString("\n")
}
}
f.WriteString("\n")
}
}
if len(modu.Docs) != 0 {
typeTag, _ := regexp.Compile(`@\w+`)
f.WriteString("## Functions\n")
for _, dps := range modu.Docs {
htmlSig := typeTag.ReplaceAllStringFunc(strings.Replace(dps.FuncSig, "<", `\<`, -1), func(typ string) string {
// todo: get type from global table to link to
// other pages (hilbish page can link to hilbish.jobs#Job)
typName := typ[1:]
linkedTyp := strings.ToLower(typName) // TODO: link
return fmt.Sprintf(`<a href="#%s" style="text-decoration: none;">%s</a>`, linkedTyp, typName)
})
f.WriteString(fmt.Sprintf("### %s\n", htmlSig))
for _, doc := range dps.Doc {
if !strings.HasPrefix(doc, "---") {
f.WriteString(doc + "\n")
}
}
f.WriteString("\n")
} }
f.WriteString("\n")
} }
}(mod, docPath, v) }(mod, docPath, v)

View File

@ -17,9 +17,8 @@ This is an alias (ha) for the `hilbish.alias` function.
### delete(name) ### delete(name)
Removes an alias. Removes an alias.
### list() -> aliases (table) ### list() -> table\<string, string>
Get a table of all aliases, with string keys as the alias and the value as the command. Get a table of all aliases, with string keys as the alias and the value as the command.
@returns table<string, string>
### resolve(alias) -> command (string) ### resolve(alias) -> command (string)
Tries to resolve an alias to its command. Tries to resolve an alias to its command.

View File

@ -14,7 +14,10 @@ Manage interactive jobs in Hilbish via Lua.
Jobs are the name of background tasks/commands. A job can be started via Jobs are the name of background tasks/commands. A job can be started via
interactive usage or with the functions defined below for use in external runners. interactive usage or with the functions defined below for use in external runners.
## Object properties ## Types
### Job
Job Type.
#### Properties
- `cmd`: The user entered command string for the job. - `cmd`: The user entered command string for the job.
- `running`: Whether the job is running or not. - `running`: Whether the job is running or not.
- `id`: The ID of the job in the job table - `id`: The ID of the job in the job table
@ -40,15 +43,15 @@ Stops the job from running.
### add(cmdstr, args, execPath) ### add(cmdstr, args, execPath)
Adds a new job to the job table. Note that this does not immediately run it. Adds a new job to the job table. Note that this does not immediately run it.
### all() -> jobs (table<Job/Table>) ### all() -> table\<<a href="#job" style="text-decoration: none;">Job</a>>
Returns a table of all job objects. Returns a table of all job objects.
### disown(id) ### disown(id)
Disowns a job. This deletes it from the job table. Disowns a job. This deletes it from the job table.
### get(id) -> job (Job/Table) ### get(id) -> <a href="#job" style="text-decoration: none;">Job</a>
Get a job object via its ID. Get a job object via its ID.
### last() -> job (Job/Table) ### last() -> <a href="#job" style="text-decoration: none;">Job</a>
Returns the last added job from the table. Returns the last added job from the table.

22
job.go
View File

@ -18,6 +18,15 @@ import (
var jobs *jobHandler var jobs *jobHandler
var jobMetaKey = rt.StringValue("hshjob") var jobMetaKey = rt.StringValue("hshjob")
// #interface jobs
// #property cmd The user entered command string for the job.
// #property running Whether the job is running or not.
// #property id The ID of the job in the job table
// #property pid The Process ID
// #property exitCode The last exit code of the job.
// #property stdout The standard output of the job. This just means the normal logs of the process.
// #property stderr The standard error stream of the process. This (usually) includes error messages of the job.
// Job Type.
type job struct { type job struct {
cmd string cmd string
running bool running bool
@ -293,13 +302,6 @@ func (j *jobHandler) stopAll() {
} }
// #interface jobs // #interface jobs
// #property cmd The user entered command string for the job.
// #property running Whether the job is running or not.
// #property id The ID of the job in the job table
// #property pid The Process ID
// #property exitCode The last exit code of the job.
// #property stdout The standard output of the job. This just means the normal logs of the process.
// #property stderr The standard error stream of the process. This (usually) includes error messages of the job.
// background job management // background job management
/* /*
Manage interactive jobs in Hilbish via Lua. Manage interactive jobs in Hilbish via Lua.
@ -384,7 +386,7 @@ func jobUserData(j *job) *rt.UserData {
} }
// #interface jobs // #interface jobs
// get(id) -> job (Job/Table) // get(id) -> @Job
// Get a job object via its ID. // Get a job object via its ID.
// --- @param id number // --- @param id number
// --- @returns Job // --- @returns Job
@ -444,7 +446,7 @@ func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
} }
// #interface jobs // #interface jobs
// all() -> jobs (table<Job/Table>) // all() -> table<@Job>
// Returns a table of all job objects. // Returns a table of all job objects.
// --- @returns table<Job> // --- @returns table<Job>
func (j *jobHandler) luaAllJobs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func (j *jobHandler) luaAllJobs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
@ -481,7 +483,7 @@ func (j *jobHandler) luaDisownJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
} }
// #interface jobs // #interface jobs
// last() -> job (Job/Table) // last() -> @Job
// Returns the last added job from the table. // Returns the last added job from the table.
// --- @returns Job // --- @returns Job
func (j *jobHandler) luaLastJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func (j *jobHandler) luaLastJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {

View File

@ -1,6 +1,11 @@
<h{{ (add .Level 1) }} id="{{ .Anchor | safeURL }}">
<h{{ (add .Level 1) }} id="{{ .Anchor | safeURL }}" class="heading">
{{ .Text | safeHTML }} {{ .Text | safeHTML }}
<a href="#{{ .Anchor | safeURL }}" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h{{ (add .Level 1) }}> </h{{ (add .Level 1) }}>
{{ if eq .Text ""}} {{ if eq .Text ""}}
<hr> <hr>
{{ end }} {{ end }}

View File

@ -1,7 +1,7 @@
<head> <head>
{{ $title := print .Title " — " .Site.Title }} {{ $title := print .Title " — " .Site.Title }}
{{ if .IsHome }}{{ $title = .Site.Title }}{{ end }} {{ if .IsHome }}{{ $title = .Site.Title }}{{ end }}
<title>{{ $title }}</title> <title>{{ $title }}</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"/> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"/>
@ -23,4 +23,16 @@
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<style>
.heading > .heading-link {
opacity: 0
}
.heading:hover > .heading-link {
visibility: visible;
opacity: 1;
transition: all .1s ease-in;
}
</style>
</head> </head>