mirror of https://github.com/Hilbis/Hilbish
refactor!: rework docs and doc command (#218)
changes the actual file format of docs to markup since that's basically what we have been using in the first place. the docgen command has been modified to write markdown headings with the function name and yaml metadata for easy consumption by hugo for the website. all other docs have been moved to markdown as well this is the main reason this is a "breaking" change users will have to reinstall hilbish (task uninstall and task install) to remove the old plaintext docspull/220/head
parent
6525fa774e
commit
e5eefb1d2d
|
@ -2,13 +2,14 @@ name: Generate docs
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [master]
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
gen:
|
gen:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-go@v2
|
- uses: actions/setup-go@v2
|
||||||
- name: Run docgen
|
- name: Run docgen
|
||||||
run: go run cmd/docgen/docgen.go
|
run: go run cmd/docgen/docgen.go
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
*.exe
|
*.exe
|
||||||
hilbish
|
hilbish
|
||||||
|
!docs/api/hilbish
|
||||||
docgen
|
docgen
|
||||||
|
!cmd/docgen
|
||||||
|
|
||||||
.vim
|
.vim
|
||||||
petals/
|
petals/
|
||||||
|
|
45
aliases.go
45
aliases.go
|
@ -9,40 +9,40 @@ import (
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
var aliases *aliasHandler
|
var aliases *aliasModule
|
||||||
|
|
||||||
type aliasHandler struct {
|
type aliasModule struct {
|
||||||
aliases map[string]string
|
aliases map[string]string
|
||||||
mu *sync.RWMutex
|
mu *sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize aliases map
|
// initialize aliases map
|
||||||
func newAliases() *aliasHandler {
|
func newAliases() *aliasModule {
|
||||||
return &aliasHandler{
|
return &aliasModule{
|
||||||
aliases: make(map[string]string),
|
aliases: make(map[string]string),
|
||||||
mu: &sync.RWMutex{},
|
mu: &sync.RWMutex{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aliasHandler) Add(alias, cmd string) {
|
func (a *aliasModule) Add(alias, cmd string) {
|
||||||
a.mu.Lock()
|
a.mu.Lock()
|
||||||
defer a.mu.Unlock()
|
defer a.mu.Unlock()
|
||||||
|
|
||||||
a.aliases[alias] = cmd
|
a.aliases[alias] = cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aliasHandler) All() map[string]string {
|
func (a *aliasModule) All() map[string]string {
|
||||||
return a.aliases
|
return a.aliases
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aliasHandler) Delete(alias string) {
|
func (a *aliasModule) Delete(alias string) {
|
||||||
a.mu.Lock()
|
a.mu.Lock()
|
||||||
defer a.mu.Unlock()
|
defer a.mu.Unlock()
|
||||||
|
|
||||||
delete(a.aliases, alias)
|
delete(a.aliases, alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aliasHandler) Resolve(cmdstr string) string {
|
func (a *aliasModule) Resolve(cmdstr string) string {
|
||||||
a.mu.RLock()
|
a.mu.RLock()
|
||||||
defer a.mu.RUnlock()
|
defer a.mu.RUnlock()
|
||||||
|
|
||||||
|
@ -66,7 +66,10 @@ func (a *aliasHandler) Resolve(cmdstr string) string {
|
||||||
|
|
||||||
// lua section
|
// lua section
|
||||||
|
|
||||||
func (a *aliasHandler) Loader(rtm *rt.Runtime) *rt.Table {
|
// #interface aliases
|
||||||
|
// command aliasing
|
||||||
|
// The alias interface deals with all command aliases in Hilbish.
|
||||||
|
func (a *aliasModule) Loader(rtm *rt.Runtime) *rt.Table {
|
||||||
// create a lua module with our functions
|
// create a lua module with our functions
|
||||||
hshaliasesLua := map[string]util.LuaExport{
|
hshaliasesLua := map[string]util.LuaExport{
|
||||||
"add": util.LuaExport{hlalias, 2, false},
|
"add": util.LuaExport{hlalias, 2, false},
|
||||||
|
@ -81,7 +84,17 @@ func (a *aliasHandler) Loader(rtm *rt.Runtime) *rt.Table {
|
||||||
return mod
|
return mod
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aliasHandler) luaList(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
// #interface aliases
|
||||||
|
// add(alias, cmd)
|
||||||
|
// This is an alias (ha) for the `hilbish.alias` function.
|
||||||
|
// --- @param alias string
|
||||||
|
// --- @param cmd string
|
||||||
|
func _hlalias() {}
|
||||||
|
|
||||||
|
// #interface aliases
|
||||||
|
// list()
|
||||||
|
// Get a table of all aliases.
|
||||||
|
func (a *aliasModule) luaList(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
aliasesList := rt.NewTable()
|
aliasesList := rt.NewTable()
|
||||||
for k, v := range a.All() {
|
for k, v := range a.All() {
|
||||||
aliasesList.Set(rt.StringValue(k), rt.StringValue(v))
|
aliasesList.Set(rt.StringValue(k), rt.StringValue(v))
|
||||||
|
@ -90,7 +103,11 @@ func (a *aliasHandler) luaList(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.PushingNext1(t.Runtime, rt.TableValue(aliasesList)), nil
|
return c.PushingNext1(t.Runtime, rt.TableValue(aliasesList)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aliasHandler) luaDelete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
// #interface aliases
|
||||||
|
// delete(name)
|
||||||
|
// Removes an alias.
|
||||||
|
// --- @param name string
|
||||||
|
func (a *aliasModule) luaDelete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -103,7 +120,11 @@ func (a *aliasHandler) luaDelete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aliasHandler) luaResolve(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
// #interface aliases
|
||||||
|
// resolve(alias)
|
||||||
|
// Tries to resolve an alias to its command.
|
||||||
|
// --- @param alias string
|
||||||
|
func (a *aliasModule) luaResolve(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
44
api.go
44
api.go
|
@ -1,6 +1,14 @@
|
||||||
// Here is the core api for the hilbi shell itself
|
// the core Hilbish API
|
||||||
// Basically, stuff about the shell itself and other functions
|
// The Hilbish module includes the core API, containing
|
||||||
// go here.
|
// interfaces and functions which directly relate to shell functionality.
|
||||||
|
// #field ver The version of Hilbish
|
||||||
|
// #field user Username of the user
|
||||||
|
// #field host Hostname of the machine
|
||||||
|
// #field dataDir Directory for Hilbish data files, including the docs and default modules
|
||||||
|
// #field interactive Is Hilbish in an interactive shell?
|
||||||
|
// #field login Is Hilbish the login shell?
|
||||||
|
// #field vimMode Current Vim input mode of Hilbish (will be nil if not in Vim input mode)
|
||||||
|
// #field exitCode xit code of the last executed command
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -19,7 +27,6 @@ import (
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
"github.com/arnodel/golua/lib/packagelib"
|
"github.com/arnodel/golua/lib/packagelib"
|
||||||
"github.com/maxlandon/readline"
|
"github.com/maxlandon/readline"
|
||||||
"github.com/blackfireio/osinfo"
|
|
||||||
"mvdan.cc/sh/v3/interp"
|
"mvdan.cc/sh/v3/interp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -114,20 +121,12 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
|
||||||
util.Document(fakeMod, "Hilbish's core API, containing submodules and functions which relate to the shell itself.")
|
util.Document(fakeMod, "Hilbish's core API, containing submodules and functions which relate to the shell itself.")
|
||||||
|
|
||||||
// hilbish.userDir table
|
// hilbish.userDir table
|
||||||
hshuser := rt.NewTable()
|
hshuser := userDirLoader(rtm)
|
||||||
|
|
||||||
util.SetField(rtm, hshuser, "config", rt.StringValue(confDir), "User's config directory")
|
|
||||||
util.SetField(rtm, hshuser, "data", rt.StringValue(userDataDir), "XDG data directory")
|
|
||||||
util.Document(hshuser, "User directories to store configs and/or modules.")
|
util.Document(hshuser, "User directories to store configs and/or modules.")
|
||||||
mod.Set(rt.StringValue("userDir"), rt.TableValue(hshuser))
|
mod.Set(rt.StringValue("userDir"), rt.TableValue(hshuser))
|
||||||
|
|
||||||
// hilbish.os table
|
// hilbish.os table
|
||||||
hshos := rt.NewTable()
|
hshos := hshosLoader(rtm)
|
||||||
info, _ := osinfo.GetOSInfo()
|
|
||||||
|
|
||||||
util.SetField(rtm, hshos, "family", rt.StringValue(info.Family), "Family name of the current OS")
|
|
||||||
util.SetField(rtm, hshos, "name", rt.StringValue(info.Name), "Pretty name of the current OS")
|
|
||||||
util.SetField(rtm, hshos, "version", rt.StringValue(info.Version), "Version of the current OS")
|
|
||||||
util.Document(hshos, "OS info interface")
|
util.Document(hshos, "OS info interface")
|
||||||
mod.Set(rt.StringValue("os"), rt.TableValue(hshos))
|
mod.Set(rt.StringValue("os"), rt.TableValue(hshos))
|
||||||
|
|
||||||
|
@ -159,10 +158,10 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
|
||||||
mod.Set(rt.StringValue("jobs"), rt.TableValue(jobModule))
|
mod.Set(rt.StringValue("jobs"), rt.TableValue(jobModule))
|
||||||
|
|
||||||
// hilbish.timers table
|
// hilbish.timers table
|
||||||
timers = newTimerHandler()
|
timers = newTimersModule()
|
||||||
timerModule := timers.loader(rtm)
|
timersModule := timers.loader(rtm)
|
||||||
util.Document(timerModule, "Timer interface, for control of all intervals and timeouts.")
|
util.Document(timersModule, "Timer interface, for control of all intervals and timeouts.")
|
||||||
mod.Set(rt.StringValue("timers"), rt.TableValue(timerModule))
|
mod.Set(rt.StringValue("timers"), rt.TableValue(timersModule))
|
||||||
|
|
||||||
editorModule := editorLoader(rtm)
|
editorModule := editorLoader(rtm)
|
||||||
util.Document(editorModule, "")
|
util.Document(editorModule, "")
|
||||||
|
@ -250,11 +249,12 @@ func hlcwd(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// read(prompt?) -> input?
|
// read(prompt) -> input
|
||||||
// Read input from the user, using Hilbish's line editor/input reader.
|
// Read input from the user, using Hilbish's line editor/input reader.
|
||||||
// This is a separate instance from the one Hilbish actually uses.
|
// This is a separate instance from the one Hilbish actually uses.
|
||||||
// Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen)
|
// Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen)
|
||||||
// --- @param prompt string
|
// --- @param prompt string|nil
|
||||||
|
// --- @returns string|nil
|
||||||
func hlread(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func hlread(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
luaprompt := c.Arg(0)
|
luaprompt := c.Arg(0)
|
||||||
if typ := luaprompt.Type(); typ != rt.StringType && typ != rt.NilType {
|
if typ := luaprompt.Type(); typ != rt.StringType && typ != rt.NilType {
|
||||||
|
@ -281,7 +281,7 @@ func hlread(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
prompt(str, typ?)
|
prompt(str, typ)
|
||||||
Changes the shell prompt to `str`
|
Changes the shell prompt to `str`
|
||||||
There are a few verbs that can be used in the prompt text.
|
There are a few verbs that can be used in the prompt text.
|
||||||
These will be formatted and replaced with the appropriate values.
|
These will be formatted and replaced with the appropriate values.
|
||||||
|
@ -289,7 +289,7 @@ These will be formatted and replaced with the appropriate values.
|
||||||
`%u` - Name of current user
|
`%u` - Name of current user
|
||||||
`%h` - Hostname of device
|
`%h` - Hostname of device
|
||||||
--- @param str string
|
--- @param str string
|
||||||
--- @param typ string Type of prompt, being left or right. Left by default.
|
--- @param typ string|nil Type of prompt, being left or right. Left by default.
|
||||||
*/
|
*/
|
||||||
func hlprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func hlprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
err := c.Check1Arg()
|
err := c.Check1Arg()
|
||||||
|
|
|
@ -9,26 +9,191 @@ import (
|
||||||
"go/token"
|
"go/token"
|
||||||
"strings"
|
"strings"
|
||||||
"os"
|
"os"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EmmyPiece struct {
|
var header = `---
|
||||||
FuncName string
|
title: %s %s
|
||||||
Docs []string
|
description: %s
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
type emmyPiece struct {
|
||||||
|
DocPiece *docPiece
|
||||||
|
Annotations []string
|
||||||
Params []string // we only need to know param name to put in function
|
Params []string // we only need to know param name to put in function
|
||||||
|
FuncName string
|
||||||
}
|
}
|
||||||
type DocPiece struct {
|
|
||||||
|
type module struct {
|
||||||
|
Docs []docPiece
|
||||||
|
Fields []docPiece
|
||||||
|
Properties []docPiece
|
||||||
|
ShortDescription string
|
||||||
|
Description string
|
||||||
|
ParentModule string
|
||||||
|
HasInterfaces bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type docPiece struct {
|
||||||
Doc []string
|
Doc []string
|
||||||
FuncSig string
|
FuncSig string
|
||||||
FuncName string
|
FuncName string
|
||||||
|
Interfacing string
|
||||||
|
ParentModule string
|
||||||
|
GoFuncName string
|
||||||
|
IsInterface bool
|
||||||
|
IsMember bool
|
||||||
|
Fields []docPiece
|
||||||
|
Properties []docPiece
|
||||||
|
}
|
||||||
|
|
||||||
|
type tag struct {
|
||||||
|
id string
|
||||||
|
fields []string
|
||||||
|
}
|
||||||
|
|
||||||
|
var docs = make(map[string]module)
|
||||||
|
var interfaceDocs = make(map[string]module)
|
||||||
|
var emmyDocs = make(map[string][]emmyPiece)
|
||||||
|
var prefix = map[string]string{
|
||||||
|
"main": "hl",
|
||||||
|
"hilbish": "hl",
|
||||||
|
"fs": "f",
|
||||||
|
"commander": "c",
|
||||||
|
"bait": "b",
|
||||||
|
"terminal": "term",
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTagsAndDocs(docs string) (map[string][]tag, []string) {
|
||||||
|
pts := strings.Split(docs, "\n")
|
||||||
|
parts := []string{}
|
||||||
|
tags := make(map[string][]tag)
|
||||||
|
|
||||||
|
for _, part := range pts {
|
||||||
|
if strings.HasPrefix(part, "#") {
|
||||||
|
tagParts := strings.Split(strings.TrimPrefix(part, "#"), " ")
|
||||||
|
if tags[tagParts[0]] == nil {
|
||||||
|
var id string
|
||||||
|
if len(tagParts) > 1 {
|
||||||
|
id = tagParts[1]
|
||||||
|
}
|
||||||
|
tags[tagParts[0]] = []tag{
|
||||||
|
{id: id},
|
||||||
|
}
|
||||||
|
if len(tagParts) >= 2 {
|
||||||
|
tags[tagParts[0]][0].fields = tagParts[2:]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fleds := []string{}
|
||||||
|
if len(tagParts) >= 2 {
|
||||||
|
fleds = tagParts[2:]
|
||||||
|
}
|
||||||
|
tags[tagParts[0]] = append(tags[tagParts[0]], tag{
|
||||||
|
id: tagParts[1],
|
||||||
|
fields: fleds,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parts = append(parts, part)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags, parts
|
||||||
|
}
|
||||||
|
|
||||||
|
func docPieceTag(tagName string, tags map[string][]tag) []docPiece {
|
||||||
|
dps := []docPiece{}
|
||||||
|
for _, tag := range tags[tagName] {
|
||||||
|
dps = append(dps, docPiece{
|
||||||
|
FuncName: tag.id,
|
||||||
|
Doc: tag.fields,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return dps
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupDoc(mod string, fun *doc.Func) *docPiece {
|
||||||
|
docs := strings.TrimSpace(fun.Doc)
|
||||||
|
inInterface := strings.HasPrefix(docs, "#interface")
|
||||||
|
if (!strings.HasPrefix(fun.Name, prefix[mod]) && !inInterface) || (strings.ToLower(fun.Name) == "loader" && !inInterface) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tags, parts := getTagsAndDocs(docs)
|
||||||
|
|
||||||
|
var interfaces string
|
||||||
|
funcsig := parts[0]
|
||||||
|
doc := parts[1:]
|
||||||
|
funcName := strings.TrimPrefix(fun.Name, prefix[mod])
|
||||||
|
funcdoc := []string{}
|
||||||
|
|
||||||
|
if inInterface {
|
||||||
|
interfaces = tags["interface"][0].id
|
||||||
|
funcName = interfaces + "." + strings.Split(funcsig, "(")[0]
|
||||||
|
}
|
||||||
|
em := emmyPiece{FuncName: funcName}
|
||||||
|
|
||||||
|
fields := docPieceTag("field", tags)
|
||||||
|
properties := docPieceTag("property", tags)
|
||||||
|
|
||||||
|
for _, d := range doc {
|
||||||
|
if strings.HasPrefix(d, "---") {
|
||||||
|
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 {
|
||||||
|
funcdoc = append(funcdoc, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var isMember bool
|
||||||
|
if tags["member"] != nil {
|
||||||
|
isMember = true
|
||||||
|
}
|
||||||
|
var parentMod string
|
||||||
|
if inInterface {
|
||||||
|
parentMod = mod
|
||||||
|
}
|
||||||
|
dps := &docPiece{
|
||||||
|
Doc: funcdoc,
|
||||||
|
FuncSig: funcsig,
|
||||||
|
FuncName: funcName,
|
||||||
|
Interfacing: interfaces,
|
||||||
|
GoFuncName: strings.ToLower(fun.Name),
|
||||||
|
IsInterface: inInterface,
|
||||||
|
IsMember: isMember,
|
||||||
|
ParentModule: parentMod,
|
||||||
|
Fields: fields,
|
||||||
|
Properties: properties,
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(dps.GoFuncName, strings.ToLower("loader")) {
|
||||||
|
dps.Doc = parts
|
||||||
|
}
|
||||||
|
em.DocPiece = dps
|
||||||
|
|
||||||
|
emmyDocs[mod] = append(emmyDocs[mod], em)
|
||||||
|
return dps
|
||||||
}
|
}
|
||||||
|
|
||||||
// feel free to clean this up
|
|
||||||
// it works, dont really care about the code
|
|
||||||
func main() {
|
func main() {
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
os.Mkdir("docs", 0777)
|
os.Mkdir("docs", 0777)
|
||||||
|
os.Mkdir("docs/api", 0777)
|
||||||
os.Mkdir("emmyLuaDocs", 0777)
|
os.Mkdir("emmyLuaDocs", 0777)
|
||||||
|
|
||||||
|
|
||||||
dirs := []string{"./"}
|
dirs := []string{"./"}
|
||||||
filepath.Walk("golibs/", func (path string, info os.FileInfo, err error) error {
|
filepath.Walk("golibs/", func (path string, info os.FileInfo, err error) error {
|
||||||
|
@ -51,120 +216,172 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prefix := map[string]string{
|
interfaceModules := make(map[string]*module)
|
||||||
"hilbish": "hl",
|
|
||||||
"fs": "f",
|
|
||||||
"commander": "c",
|
|
||||||
"bait": "b",
|
|
||||||
"terminal": "term",
|
|
||||||
}
|
|
||||||
docs := make(map[string][]DocPiece)
|
|
||||||
emmyDocs := make(map[string][]EmmyPiece)
|
|
||||||
|
|
||||||
for l, f := range pkgs {
|
for l, f := range pkgs {
|
||||||
p := doc.New(f, "./", doc.AllDecls)
|
p := doc.New(f, "./", doc.AllDecls)
|
||||||
|
pieces := []docPiece{}
|
||||||
|
mod := l
|
||||||
|
if mod == "main" {
|
||||||
|
mod = "hilbish"
|
||||||
|
}
|
||||||
|
var hasInterfaces bool
|
||||||
for _, t := range p.Funcs {
|
for _, t := range p.Funcs {
|
||||||
mod := l
|
piece := setupDoc(mod, t)
|
||||||
if strings.HasPrefix(t.Name, "hl") { mod = "hilbish" }
|
if piece == nil {
|
||||||
if !strings.HasPrefix(t.Name, prefix[mod]) || t.Name == "Loader" { continue }
|
continue
|
||||||
parts := strings.Split(strings.TrimSpace(t.Doc), "\n")
|
|
||||||
funcsig := parts[0]
|
|
||||||
doc := parts[1:]
|
|
||||||
funcdoc := []string{}
|
|
||||||
em := EmmyPiece{FuncName: strings.TrimPrefix(t.Name, prefix[mod])}
|
|
||||||
for _, d := range doc {
|
|
||||||
if strings.HasPrefix(d, "---") {
|
|
||||||
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.Docs = append(em.Docs, d)
|
|
||||||
} else {
|
|
||||||
funcdoc = append(funcdoc, d)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dps := DocPiece{
|
pieces = append(pieces, *piece)
|
||||||
Doc: funcdoc,
|
if piece.IsInterface {
|
||||||
FuncSig: funcsig,
|
hasInterfaces = true
|
||||||
FuncName: strings.TrimPrefix(t.Name, prefix[mod]),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
docs[mod] = append(docs[mod], dps)
|
|
||||||
emmyDocs[mod] = append(emmyDocs[mod], em)
|
|
||||||
}
|
}
|
||||||
for _, t := range p.Types {
|
for _, t := range p.Types {
|
||||||
for _, m := range t.Methods {
|
for _, m := range t.Methods {
|
||||||
if !strings.HasPrefix(m.Name, prefix[l]) || m.Name == "Loader" { continue }
|
piece := setupDoc(mod, m)
|
||||||
parts := strings.Split(strings.TrimSpace(m.Doc), "\n")
|
if piece == nil {
|
||||||
funcsig := parts[0]
|
continue
|
||||||
doc := parts[1:]
|
|
||||||
funcdoc := []string{}
|
|
||||||
em := EmmyPiece{FuncName: strings.TrimPrefix(m.Name, prefix[l])}
|
|
||||||
for _, d := range doc {
|
|
||||||
if strings.HasPrefix(d, "---") {
|
|
||||||
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.Docs = append(em.Docs, d)
|
|
||||||
} else {
|
|
||||||
funcdoc = append(funcdoc, d)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dps := DocPiece{
|
|
||||||
Doc: funcdoc,
|
|
||||||
FuncSig: funcsig,
|
|
||||||
FuncName: strings.TrimPrefix(m.Name, prefix[l]),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
docs[l] = append(docs[l], dps)
|
pieces = append(pieces, *piece)
|
||||||
emmyDocs[l] = append(emmyDocs[l], em)
|
if piece.IsInterface {
|
||||||
|
hasInterfaces = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tags, descParts := getTagsAndDocs(strings.TrimSpace(p.Doc))
|
||||||
|
shortDesc := descParts[0]
|
||||||
|
desc := descParts[1:]
|
||||||
|
filteredPieces := []docPiece{}
|
||||||
|
for _, piece := range pieces {
|
||||||
|
if !piece.IsInterface {
|
||||||
|
filteredPieces = append(filteredPieces, piece)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
modname := piece.ParentModule + "." + piece.Interfacing
|
||||||
|
if interfaceModules[modname] == nil {
|
||||||
|
interfaceModules[modname] = &module{
|
||||||
|
ParentModule: piece.ParentModule,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(piece.GoFuncName, strings.ToLower("loader")) {
|
||||||
|
shortDesc := piece.Doc[0]
|
||||||
|
desc := piece.Doc[1:]
|
||||||
|
interfaceModules[modname].ShortDescription = shortDesc
|
||||||
|
interfaceModules[modname].Description = strings.Join(desc, "\n")
|
||||||
|
interfaceModules[modname].Fields = piece.Fields
|
||||||
|
interfaceModules[modname].Properties = piece.Properties
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
interfaceModules[modname].Docs = append(interfaceModules[modname].Docs, piece)
|
||||||
|
}
|
||||||
|
|
||||||
|
docs[mod] = module{
|
||||||
|
Docs: filteredPieces,
|
||||||
|
ShortDescription: shortDesc,
|
||||||
|
Description: strings.Join(desc, "\n"),
|
||||||
|
HasInterfaces: hasInterfaces,
|
||||||
|
Properties: docPieceTag("property", tags),
|
||||||
|
Fields: docPieceTag("field", tags),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for key, mod := range interfaceModules {
|
||||||
|
docs[key] = *mod
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(docs) * 2)
|
||||||
|
|
||||||
for mod, v := range docs {
|
for mod, v := range docs {
|
||||||
if mod == "main" { continue }
|
docPath := "docs/api/" + mod + ".md"
|
||||||
f, _ := os.Create("docs/" + mod + ".txt")
|
if v.HasInterfaces {
|
||||||
for _, dps := range v {
|
os.Mkdir("docs/api/" + mod, 0777)
|
||||||
f.WriteString(dps.FuncSig + " > ")
|
os.Remove(docPath) // remove old doc path if it exists
|
||||||
for _, doc := range dps.Doc {
|
docPath = "docs/api/" + mod + "/_index.md"
|
||||||
if !strings.HasPrefix(doc, "---") {
|
|
||||||
f.WriteString(doc + "\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f.WriteString("\n")
|
|
||||||
}
|
}
|
||||||
}
|
if v.ParentModule != "" {
|
||||||
|
docPath = "docs/api/" + v.ParentModule + "/" + mod + ".md"
|
||||||
for mod, v := range emmyDocs {
|
|
||||||
if mod == "main" { continue }
|
|
||||||
f, _ := os.Create("emmyLuaDocs/" + mod + ".lua")
|
|
||||||
f.WriteString("--- @meta\n\nlocal " + mod + " = {}\n\n")
|
|
||||||
for _, em := range v {
|
|
||||||
var funcdocs []string
|
|
||||||
for _, dps := range docs[mod] {
|
|
||||||
if dps.FuncName == em.FuncName {
|
|
||||||
funcdocs = dps.Doc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f.WriteString("--- " + strings.Join(funcdocs, "\n--- ") + "\n")
|
|
||||||
if len(em.Docs) != 0 {
|
|
||||||
f.WriteString(strings.Join(em.Docs, "\n") + "\n")
|
|
||||||
}
|
|
||||||
f.WriteString("function " + mod + "." + em.FuncName + "(" + strings.Join(em.Params, ", ") + ") end\n\n")
|
|
||||||
}
|
}
|
||||||
f.WriteString("return " + mod + "\n")
|
|
||||||
|
go func(modname, docPath string, modu module) {
|
||||||
|
defer wg.Done()
|
||||||
|
modOrIface := "Module"
|
||||||
|
if modu.ParentModule != "" {
|
||||||
|
modOrIface = "Interface"
|
||||||
|
}
|
||||||
|
|
||||||
|
f, _ := os.Create(docPath)
|
||||||
|
f.WriteString(fmt.Sprintf(header, modOrIface, modname, modu.ShortDescription))
|
||||||
|
f.WriteString(fmt.Sprintf("## Introduction\n%s\n\n", modu.Description))
|
||||||
|
if len(modu.Fields) != 0 {
|
||||||
|
f.WriteString("## Interface fields\n")
|
||||||
|
for _, dps := range modu.Fields {
|
||||||
|
f.WriteString(fmt.Sprintf("- `%s`: ", dps.FuncName))
|
||||||
|
f.WriteString(strings.Join(dps.Doc, " "))
|
||||||
|
f.WriteString("\n")
|
||||||
|
}
|
||||||
|
f.WriteString("\n")
|
||||||
|
}
|
||||||
|
if len(modu.Properties) != 0 {
|
||||||
|
f.WriteString("## Object properties\n")
|
||||||
|
for _, dps := range modu.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 {
|
||||||
|
f.WriteString("## Functions\n")
|
||||||
|
}
|
||||||
|
for _, dps := range modu.Docs {
|
||||||
|
f.WriteString(fmt.Sprintf("### %s\n", dps.FuncSig))
|
||||||
|
for _, doc := range dps.Doc {
|
||||||
|
if !strings.HasPrefix(doc, "---") {
|
||||||
|
f.WriteString(doc + "\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.WriteString("\n")
|
||||||
|
}
|
||||||
|
}(mod, docPath, v)
|
||||||
|
|
||||||
|
go func(md, modname string, modu module) {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
if modu.ParentModule != "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ff, _ := os.Create("emmyLuaDocs/" + modname + ".lua")
|
||||||
|
ff.WriteString("--- @meta\n\nlocal " + modname + " = {}\n\n")
|
||||||
|
for _, em := range emmyDocs[modname] {
|
||||||
|
if strings.HasSuffix(em.DocPiece.GoFuncName, strings.ToLower("loader")) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
dps := em.DocPiece
|
||||||
|
funcdocs := dps.Doc
|
||||||
|
ff.WriteString("--- " + strings.Join(funcdocs, "\n--- ") + "\n")
|
||||||
|
if len(em.Annotations) != 0 {
|
||||||
|
ff.WriteString(strings.Join(em.Annotations, "\n") + "\n")
|
||||||
|
}
|
||||||
|
accessor := "."
|
||||||
|
if dps.IsMember {
|
||||||
|
accessor = ":"
|
||||||
|
}
|
||||||
|
signature := strings.Split(dps.FuncSig, " ->")[0]
|
||||||
|
var intrface string
|
||||||
|
if dps.IsInterface {
|
||||||
|
intrface = "." + dps.Interfacing
|
||||||
|
}
|
||||||
|
ff.WriteString("function " + modname + intrface + accessor + signature + " end\n\n")
|
||||||
|
}
|
||||||
|
ff.WriteString("return " + modname + "\n")
|
||||||
|
}(mod, mod, v)
|
||||||
}
|
}
|
||||||
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
19
complete.go
19
complete.go
|
@ -172,6 +172,9 @@ func escapeFilename(fname string) string {
|
||||||
return escapeReplaer.Replace(fname)
|
return escapeReplaer.Replace(fname)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface completions
|
||||||
|
// tab completions
|
||||||
|
// The completions interface deals with tab completions.
|
||||||
func completionLoader(rtm *rt.Runtime) *rt.Table {
|
func completionLoader(rtm *rt.Runtime) *rt.Table {
|
||||||
exports := map[string]util.LuaExport{
|
exports := map[string]util.LuaExport{
|
||||||
"files": {luaFileComplete, 3, false},
|
"files": {luaFileComplete, 3, false},
|
||||||
|
@ -186,11 +189,19 @@ func completionLoader(rtm *rt.Runtime) *rt.Table {
|
||||||
return mod
|
return mod
|
||||||
}
|
}
|
||||||
|
|
||||||
// left as a shim, might doc in the same way as hilbish functions
|
// #interface completions
|
||||||
|
// handler(line, pos)
|
||||||
|
// The handler function is the callback for tab completion in Hilbish.
|
||||||
|
// You can check the completions doc for more info.
|
||||||
func completionHandler(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func completionHandler(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface completions
|
||||||
|
// call(name, query, ctx, fields)
|
||||||
|
// Calls a completer function. This is mainly used to call
|
||||||
|
// a command completer, which will have a `name` in the form
|
||||||
|
// of `command.name`, example: `command.git`
|
||||||
func callLuaCompleter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func callLuaCompleter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.CheckNArgs(4); err != nil {
|
if err := c.CheckNArgs(4); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -230,6 +241,9 @@ func callLuaCompleter(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.PushingNext1(t.Runtime, completerReturn), nil
|
return c.PushingNext1(t.Runtime, completerReturn), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface completions
|
||||||
|
// files(query, ctx, fields)
|
||||||
|
// Returns file completion candidates based on the provided query.
|
||||||
func luaFileComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func luaFileComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
query, ctx, fds, err := getCompleteParams(t, c)
|
query, ctx, fds, err := getCompleteParams(t, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -246,6 +260,9 @@ func luaFileComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.PushingNext(t.Runtime, rt.TableValue(luaComps), rt.StringValue(pfx)), nil
|
return c.PushingNext(t.Runtime, rt.TableValue(luaComps), rt.StringValue(pfx)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface completions
|
||||||
|
// bins(query, ctx, fields)
|
||||||
|
// Returns binary/executale completion candidates based on the provided query.
|
||||||
func luaBinaryComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func luaBinaryComplete(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
query, ctx, fds, err := getCompleteParams(t, c)
|
query, ctx, fds, err := getCompleteParams(t, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
title: API
|
||||||
|
layout: doc
|
||||||
|
weight: -50
|
||||||
|
menu: docs
|
||||||
|
---
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
title: Module bait
|
||||||
|
description: the event emitter
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
Bait is the event emitter for Hilbish. Why name it bait? Why not.
|
||||||
|
It throws hooks that you can catch. This is what you will use if
|
||||||
|
you want to listen in on hooks to know when certain things have
|
||||||
|
happened, like when you've changed directory, a command has failed,
|
||||||
|
etc. To find all available hooks thrown by Hilbish, see doc hooks.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### catch(name, cb)
|
||||||
|
Catches a hook with `name`. Runs the `cb` when it is thrown
|
||||||
|
|
||||||
|
### catchOnce(name, cb)
|
||||||
|
Same as catch, but only runs the `cb` once and then removes the hook
|
||||||
|
|
||||||
|
### hooks(name) -> {cb, cb...}
|
||||||
|
Returns a table with hooks on the event with `name`.
|
||||||
|
|
||||||
|
### release(name, catcher)
|
||||||
|
Removes the `catcher` for the event with `name`
|
||||||
|
For this to work, `catcher` has to be the same function used to catch
|
||||||
|
an event, like one saved to a variable.
|
||||||
|
|
||||||
|
### throw(name, ...args)
|
||||||
|
Throws a hook with `name` with the provided `args`
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
title: Module commander
|
||||||
|
description: library for custom commands
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
Commander is a library for writing custom commands in Lua.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### deregister(name)
|
||||||
|
Deregisters any command registered with `name`
|
||||||
|
|
||||||
|
### register(name, cb)
|
||||||
|
Register a command with `name` that runs `cb` when ran
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
title: Module fs
|
||||||
|
description: filesystem interaction and functionality library
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
The fs module provides easy and simple access to filesystem functions
|
||||||
|
and other things, and acts an addition to the Lua standard library's
|
||||||
|
I/O and filesystem functions.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### abs(path)
|
||||||
|
Gives an absolute version of `path`.
|
||||||
|
|
||||||
|
### basename(path)
|
||||||
|
Gives the basename of `path`. For the rules,
|
||||||
|
see Go's filepath.Base
|
||||||
|
|
||||||
|
### cd(dir)
|
||||||
|
Changes directory to `dir`
|
||||||
|
|
||||||
|
### dir(path)
|
||||||
|
Returns the directory part of `path`. For the rules, see Go's
|
||||||
|
filepath.Dir
|
||||||
|
|
||||||
|
### glob(pattern)
|
||||||
|
Glob all files and directories that match the pattern.
|
||||||
|
For the rules, see Go's filepath.Glob
|
||||||
|
|
||||||
|
### join(paths...)
|
||||||
|
Takes paths and joins them together with the OS's
|
||||||
|
directory separator (forward or backward slash).
|
||||||
|
|
||||||
|
### mkdir(name, recursive)
|
||||||
|
Makes a directory called `name`. If `recursive` is true, it will create its parent directories.
|
||||||
|
|
||||||
|
### readdir(dir)
|
||||||
|
Returns a table of files in `dir`
|
||||||
|
|
||||||
|
### stat(path)
|
||||||
|
Returns info about `path`
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
---
|
||||||
|
title: Module hilbish
|
||||||
|
description: the core Hilbish API
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
The Hilbish module includes the core API, containing
|
||||||
|
interfaces and functions which directly relate to shell functionality.
|
||||||
|
|
||||||
|
## Interface fields
|
||||||
|
- `ver`: The version of Hilbish
|
||||||
|
- `user`: Username of the user
|
||||||
|
- `host`: Hostname of the machine
|
||||||
|
- `dataDir`: Directory for Hilbish data files, including the docs and default modules
|
||||||
|
- `interactive`: Is Hilbish in an interactive shell?
|
||||||
|
- `login`: Is Hilbish the login shell?
|
||||||
|
- `vimMode`: Current Vim input mode of Hilbish (will be nil if not in Vim input mode)
|
||||||
|
- `exitCode`: xit code of the last executed command
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### alias(cmd, orig)
|
||||||
|
Sets an alias of `cmd` to `orig`
|
||||||
|
|
||||||
|
### appendPath(dir)
|
||||||
|
Appends `dir` to $PATH
|
||||||
|
|
||||||
|
### complete(scope, cb)
|
||||||
|
Registers a completion handler for `scope`.
|
||||||
|
A `scope` is currently only expected to be `command.<cmd>`,
|
||||||
|
replacing <cmd> with the name of the command (for example `command.git`).
|
||||||
|
`cb` must be a function that returns a table of "completion groups."
|
||||||
|
Check `doc completions` for more information.
|
||||||
|
|
||||||
|
### cwd()
|
||||||
|
Returns the current directory of the shell
|
||||||
|
|
||||||
|
### exec(cmd)
|
||||||
|
Replaces running hilbish with `cmd`
|
||||||
|
|
||||||
|
### goro(fn)
|
||||||
|
Puts `fn` in a goroutine
|
||||||
|
|
||||||
|
### highlighter(line)
|
||||||
|
Line highlighter handler. This is mainly for syntax highlighting, but in
|
||||||
|
reality could set the input of the prompt to *display* anything. The
|
||||||
|
callback is passed the current line and is expected to return a line that
|
||||||
|
will be used as the input display.
|
||||||
|
|
||||||
|
### hinter(line, pos)
|
||||||
|
The command line hint handler. It gets called on every key insert to
|
||||||
|
determine what text to use as an inline hint. It is passed the current
|
||||||
|
line and cursor position. It is expected to return a string which is used
|
||||||
|
as the text for the hint. This is by default a shim. To set hints,
|
||||||
|
override this function with your custom handler.
|
||||||
|
|
||||||
|
### inputMode(mode)
|
||||||
|
Sets the input mode for Hilbish's line reader. Accepts either emacs or vim
|
||||||
|
|
||||||
|
### interval(cb, time)
|
||||||
|
Runs the `cb` function every `time` milliseconds.
|
||||||
|
Returns a `timer` object (see `doc timers`).
|
||||||
|
|
||||||
|
### multiprompt(str)
|
||||||
|
Changes the continued line prompt to `str`
|
||||||
|
|
||||||
|
### prependPath(dir)
|
||||||
|
Prepends `dir` to $PATH
|
||||||
|
|
||||||
|
### prompt(str, typ)
|
||||||
|
Changes the shell prompt to `str`
|
||||||
|
There are a few verbs that can be used in the prompt text.
|
||||||
|
These will be formatted and replaced with the appropriate values.
|
||||||
|
`%d` - Current working directory
|
||||||
|
`%u` - Name of current user
|
||||||
|
`%h` - Hostname of device
|
||||||
|
|
||||||
|
### read(prompt) -> input
|
||||||
|
Read input from the user, using Hilbish's line editor/input reader.
|
||||||
|
This is a separate instance from the one Hilbish actually uses.
|
||||||
|
Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen)
|
||||||
|
|
||||||
|
### run(cmd, returnOut) -> exitCode, stdout, stderr
|
||||||
|
Runs `cmd` in Hilbish's sh interpreter.
|
||||||
|
If returnOut is true, the outputs of `cmd` will be returned as the 2nd and
|
||||||
|
3rd values instead of being outputted to the terminal.
|
||||||
|
|
||||||
|
### runnerMode(mode)
|
||||||
|
Sets the execution/runner mode for interactive Hilbish. This determines whether
|
||||||
|
Hilbish wll try to run input as Lua and/or sh or only do one of either.
|
||||||
|
Accepted values for mode are hybrid (the default), hybridRev (sh first then Lua),
|
||||||
|
sh, and lua. It also accepts a function, to which if it is passed one
|
||||||
|
will call it to execute user input instead.
|
||||||
|
|
||||||
|
### timeout(cb, time)
|
||||||
|
Runs the `cb` function after `time` in milliseconds
|
||||||
|
Returns a `timer` object (see `doc timers`).
|
||||||
|
|
||||||
|
### which(name)
|
||||||
|
Checks if `name` is a valid command
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
title: Interface hilbish.aliases
|
||||||
|
description: command aliasing
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
The alias interface deals with all command aliases in Hilbish.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### add(alias, cmd)
|
||||||
|
This is an alias (ha) for the `hilbish.alias` function.
|
||||||
|
|
||||||
|
### delete(name)
|
||||||
|
Removes an alias.
|
||||||
|
|
||||||
|
### list()
|
||||||
|
Get a table of all aliases.
|
||||||
|
|
||||||
|
### resolve(alias)
|
||||||
|
Tries to resolve an alias to its command.
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
title: Interface hilbish.completions
|
||||||
|
description: tab completions
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
The completions interface deals with tab completions.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### call(name, query, ctx, fields)
|
||||||
|
Calls a completer function. This is mainly used to call
|
||||||
|
a command completer, which will have a `name` in the form
|
||||||
|
of `command.name`, example: `command.git`
|
||||||
|
|
||||||
|
### handler(line, pos)
|
||||||
|
The handler function is the callback for tab completion in Hilbish.
|
||||||
|
You can check the completions doc for more info.
|
||||||
|
|
||||||
|
### bins(query, ctx, fields)
|
||||||
|
Returns binary/executale completion candidates based on the provided query.
|
||||||
|
|
||||||
|
### files(query, ctx, fields)
|
||||||
|
Returns file completion candidates based on the provided query.
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
title: Interface hilbish.editor
|
||||||
|
description: interactions for Hilbish's line reader
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
The hilbish.editor interface provides functions to
|
||||||
|
directly interact with the line editor in use.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### getLine()
|
||||||
|
Returns the current input line.
|
||||||
|
|
||||||
|
### getVimRegister(register)
|
||||||
|
Returns the text that is at the register.
|
||||||
|
|
||||||
|
### insert(text)
|
||||||
|
Inserts text into the line.
|
||||||
|
|
||||||
|
### setVimRegister(register, text)
|
||||||
|
Sets the vim register at `register` to hold the passed text.
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
title: Interface hilbish.history
|
||||||
|
description: command history
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
The history interface deals with command history.
|
||||||
|
This includes the ability to override functions to change the main
|
||||||
|
method of saving history.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### add(cmd)
|
||||||
|
Adds a command to the history.
|
||||||
|
|
||||||
|
### clear()
|
||||||
|
Deletes all commands from the history.
|
||||||
|
|
||||||
|
### get(idx)
|
||||||
|
Retrieves a command from the history based on the `idx`.
|
||||||
|
|
||||||
|
### size()
|
||||||
|
Returns the amount of commands in the history.
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
---
|
||||||
|
title: Interface hilbish.jobs
|
||||||
|
description: background job management
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
Manage interactive jobs in Hilbish via Lua.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Object properties
|
||||||
|
- `cmd`: The user entered command string for the job.
|
||||||
|
- `running`: Whether the job is running or not.
|
||||||
|
- `id`: The ID of the job in the job table
|
||||||
|
- `pid`: The Process ID
|
||||||
|
- `exitCode`: The last exit code of the job.
|
||||||
|
- `stdout`: The standard output of the job. This just means the normal logs of the process.
|
||||||
|
- `stderr`: The standard error stream of the process. This (usually) includes error messages of the job.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### background()
|
||||||
|
Puts a job in the background. This acts the same as initially running a job.
|
||||||
|
|
||||||
|
### foreground()
|
||||||
|
Puts a job in the foreground. This will cause it to run like it was
|
||||||
|
executed normally and wait for it to complete.
|
||||||
|
|
||||||
|
### start()
|
||||||
|
Starts running the job.
|
||||||
|
|
||||||
|
### stop()
|
||||||
|
Stops the job from running.
|
||||||
|
|
||||||
|
### add(cmdstr, args, execPath)
|
||||||
|
Adds a new job to the job table. Note that this does not immediately run it.
|
||||||
|
|
||||||
|
### all()
|
||||||
|
Returns a table of all job objects.
|
||||||
|
|
||||||
|
### disown(id)
|
||||||
|
Disowns a job. This deletes it from the job table.
|
||||||
|
|
||||||
|
### get(id)
|
||||||
|
Get a job object via its ID.
|
||||||
|
|
||||||
|
### last() -> Job
|
||||||
|
Returns the last added job from the table.
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
title: Interface hilbish.os
|
||||||
|
description: OS Info
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
The `os` interface provides simple text information properties about
|
||||||
|
the current OS on the systen. This mainly includes the name and
|
||||||
|
version.
|
||||||
|
|
||||||
|
## Interface fields
|
||||||
|
- `family`: Family name of the current OS
|
||||||
|
- `name`: Pretty name of the current OS
|
||||||
|
- `version`: Version of the current OS
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
---
|
||||||
|
title: Interface hilbish.runner
|
||||||
|
description: interactive command runner customization
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
The runner interface contains functions that allow the user to change
|
||||||
|
how Hilbish interprets interactive input.
|
||||||
|
Users can add and change the default runner for interactive input to any
|
||||||
|
language or script of their choosing. A good example is using it to
|
||||||
|
write command in Fennel.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### setMode(cb)
|
||||||
|
This is the same as the `hilbish.runnerMode` function. It takes a callback,
|
||||||
|
which will be used to execute all interactive input.
|
||||||
|
In normal cases, neither callbacks should be overrided by the user,
|
||||||
|
as the higher level functions listed below this will handle it.
|
||||||
|
|
||||||
|
### lua(cmd)
|
||||||
|
Evaluates `cmd` as Lua input. This is the same as using `dofile`
|
||||||
|
or `load`, but is appropriated for the runner interface.
|
||||||
|
|
||||||
|
### sh(cmd)
|
||||||
|
Runs a command in Hilbish's shell script interpreter.
|
||||||
|
This is the equivalent of using `source`.
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
title: Interface hilbish.timers
|
||||||
|
description: timeout and interval API
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
The timers interface si one to easily set timeouts and intervals
|
||||||
|
to run functions after a certain time or repeatedly without using
|
||||||
|
odd tricks.
|
||||||
|
|
||||||
|
## Object properties
|
||||||
|
- `type`: What type of timer it is
|
||||||
|
- `running`: If the timer is running
|
||||||
|
- `duration`: The duration in milliseconds that the timer will run
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### start()
|
||||||
|
Starts a timer.
|
||||||
|
|
||||||
|
### stop()
|
||||||
|
Stops a timer.
|
||||||
|
|
||||||
|
### create(type, time, callback)
|
||||||
|
Creates a timer that runs based on the specified `time` in milliseconds.
|
||||||
|
The `type` can either be interval (value of 0) or timeout (value of 1).
|
||||||
|
|
||||||
|
### get(id)
|
||||||
|
Retrieves a timer via its ID.
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
title: Interface hilbish.userDir
|
||||||
|
description: user-related directories
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
This interface just contains properties to know about certain user directories.
|
||||||
|
It is equivalent to XDG on Linux and gets the user's preferred directories
|
||||||
|
for configs and data.
|
||||||
|
|
||||||
|
## Interface fields
|
||||||
|
- `config`: The user's config directory
|
||||||
|
- `data`: The user's directory for program data
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
title: Module terminal
|
||||||
|
description: low level terminal library
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "API"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
The terminal library is a simple and lower level library for certain terminal interactions.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
### restoreState()
|
||||||
|
Restores the last saved state of the terminal
|
||||||
|
|
||||||
|
### saveState()
|
||||||
|
Saves the current state of the terminal
|
||||||
|
|
||||||
|
### setRaw()
|
||||||
|
Puts the terminal in raw mode
|
||||||
|
|
||||||
|
### size()
|
||||||
|
Gets the dimensions of the terminal. Returns a table with `width` and `height`
|
||||||
|
Note: this is not the size in relation to the dimensions of the display
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
catch(name, cb) > Catches a hook with `name`. Runs the `cb` when it is thrown
|
|
||||||
|
|
||||||
catchOnce(name, cb) > Same as catch, but only runs the `cb` once and then removes the hook
|
|
||||||
|
|
||||||
hooks(name) -> {cb, cb...} > Returns a table with hooks on the event with `name`.
|
|
||||||
|
|
||||||
release(name, catcher) > Removes the `catcher` for the event with `name`
|
|
||||||
For this to work, `catcher` has to be the same function used to catch
|
|
||||||
an event, like one saved to a variable.
|
|
||||||
|
|
||||||
throw(name, ...args) > Throws a hook with `name` with the provided `args`
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
deregister(name) > Deregisters any command registered with `name`
|
|
||||||
|
|
||||||
register(name, cb) > Register a command with `name` that runs `cb` when ran
|
|
||||||
|
|
22
docs/fs.txt
22
docs/fs.txt
|
@ -1,22 +0,0 @@
|
||||||
abs(path) > Gives an absolute version of `path`.
|
|
||||||
|
|
||||||
basename(path) > Gives the basename of `path`. For the rules,
|
|
||||||
see Go's filepath.Base
|
|
||||||
|
|
||||||
cd(dir) > Changes directory to `dir`
|
|
||||||
|
|
||||||
dir(path) > Returns the directory part of `path`. For the rules, see Go's
|
|
||||||
filepath.Dir
|
|
||||||
|
|
||||||
glob(pattern) > Glob all files and directories that match the pattern.
|
|
||||||
For the rules, see Go's filepath.Glob
|
|
||||||
|
|
||||||
join(paths...) > Takes paths and joins them together with the OS's
|
|
||||||
directory separator (forward or backward slash).
|
|
||||||
|
|
||||||
mkdir(name, recursive) > Makes a directory called `name`. If `recursive` is true, it will create its parent directories.
|
|
||||||
|
|
||||||
readdir(dir) > Returns a table of files in `dir`
|
|
||||||
|
|
||||||
stat(path) > Returns info about `path`
|
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
alias(cmd, orig) > Sets an alias of `cmd` to `orig`
|
|
||||||
|
|
||||||
appendPath(dir) > Appends `dir` to $PATH
|
|
||||||
|
|
||||||
complete(scope, cb) > Registers a completion handler for `scope`.
|
|
||||||
A `scope` is currently only expected to be `command.<cmd>`,
|
|
||||||
replacing <cmd> with the name of the command (for example `command.git`).
|
|
||||||
`cb` must be a function that returns a table of "completion groups."
|
|
||||||
Check `doc completions` for more information.
|
|
||||||
|
|
||||||
cwd() > Returns the current directory of the shell
|
|
||||||
|
|
||||||
exec(cmd) > Replaces running hilbish with `cmd`
|
|
||||||
|
|
||||||
goro(fn) > Puts `fn` in a goroutine
|
|
||||||
|
|
||||||
highlighter(line) > Line highlighter handler. This is mainly for syntax highlighting, but in
|
|
||||||
reality could set the input of the prompt to *display* anything. The
|
|
||||||
callback is passed the current line and is expected to return a line that
|
|
||||||
will be used as the input display.
|
|
||||||
|
|
||||||
hinter(line, pos) > The command line hint handler. It gets called on every key insert to
|
|
||||||
determine what text to use as an inline hint. It is passed the current
|
|
||||||
line and cursor position. It is expected to return a string which is used
|
|
||||||
as the text for the hint. This is by default a shim. To set hints,
|
|
||||||
override this function with your custom handler.
|
|
||||||
|
|
||||||
inputMode(mode) > Sets the input mode for Hilbish's line reader. Accepts either emacs or vim
|
|
||||||
|
|
||||||
interval(cb, time) > Runs the `cb` function every `time` milliseconds.
|
|
||||||
Returns a `timer` object (see `doc timers`).
|
|
||||||
|
|
||||||
multiprompt(str) > Changes the continued line prompt to `str`
|
|
||||||
|
|
||||||
prependPath(dir) > Prepends `dir` to $PATH
|
|
||||||
|
|
||||||
prompt(str, typ?) > Changes the shell prompt to `str`
|
|
||||||
There are a few verbs that can be used in the prompt text.
|
|
||||||
These will be formatted and replaced with the appropriate values.
|
|
||||||
`%d` - Current working directory
|
|
||||||
`%u` - Name of current user
|
|
||||||
`%h` - Hostname of device
|
|
||||||
|
|
||||||
read(prompt?) -> input? > Read input from the user, using Hilbish's line editor/input reader.
|
|
||||||
This is a separate instance from the one Hilbish actually uses.
|
|
||||||
Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen)
|
|
||||||
|
|
||||||
run(cmd, returnOut) -> exitCode, stdout, stderr > Runs `cmd` in Hilbish's sh interpreter.
|
|
||||||
If returnOut is true, the outputs of `cmd` will be returned as the 2nd and
|
|
||||||
3rd values instead of being outputted to the terminal.
|
|
||||||
|
|
||||||
runnerMode(mode) > Sets the execution/runner mode for interactive Hilbish. This determines whether
|
|
||||||
Hilbish wll try to run input as Lua and/or sh or only do one of either.
|
|
||||||
Accepted values for mode are hybrid (the default), hybridRev (sh first then Lua),
|
|
||||||
sh, and lua. It also accepts a function, to which if it is passed one
|
|
||||||
will call it to execute user input instead.
|
|
||||||
|
|
||||||
timeout(cb, time) > Runs the `cb` function after `time` in milliseconds
|
|
||||||
Returns a `timer` object (see `doc timers`).
|
|
||||||
|
|
||||||
which(name) > Checks if `name` is a valid command
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
restoreState() > Restores the last saved state of the terminal
|
|
||||||
|
|
||||||
saveState() > Saves the current state of the terminal
|
|
||||||
|
|
||||||
setRaw() > Puts the terminal in raw mode
|
|
||||||
|
|
||||||
size() > Gets the dimensions of the terminal. Returns a table with `width` and `height`
|
|
||||||
Note: this is not the size in relation to the dimensions of the display
|
|
||||||
|
|
16
editor.go
16
editor.go
|
@ -6,6 +6,10 @@ import (
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// #interface editor
|
||||||
|
// interactions for Hilbish's line reader
|
||||||
|
// The hilbish.editor interface provides functions to
|
||||||
|
// directly interact with the line editor in use.
|
||||||
func editorLoader(rtm *rt.Runtime) *rt.Table {
|
func editorLoader(rtm *rt.Runtime) *rt.Table {
|
||||||
exports := map[string]util.LuaExport{
|
exports := map[string]util.LuaExport{
|
||||||
"insert": {editorInsert, 1, false},
|
"insert": {editorInsert, 1, false},
|
||||||
|
@ -20,6 +24,9 @@ func editorLoader(rtm *rt.Runtime) *rt.Table {
|
||||||
return mod
|
return mod
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface editor
|
||||||
|
// insert(text)
|
||||||
|
// Inserts text into the line.
|
||||||
func editorInsert(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func editorInsert(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -35,6 +42,9 @@ func editorInsert(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface editor
|
||||||
|
// setVimRegister(register, text)
|
||||||
|
// Sets the vim register at `register` to hold the passed text.
|
||||||
func editorSetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func editorSetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -55,6 +65,9 @@ func editorSetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface editor
|
||||||
|
// getVimRegister(register)
|
||||||
|
// Returns the text that is at the register.
|
||||||
func editorGetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func editorGetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -70,6 +83,9 @@ func editorGetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
|
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface editor
|
||||||
|
// getLine()
|
||||||
|
// Returns the current input line.
|
||||||
func editorGetLine(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func editorGetLine(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
buf := lr.rl.GetLine()
|
buf := lr.rl.GetLine()
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,6 @@ function bait.release(name, catcher) end
|
||||||
--- Throws a hook with `name` with the provided `args`
|
--- Throws a hook with `name` with the provided `args`
|
||||||
--- @param name string
|
--- @param name string
|
||||||
--- @vararg any
|
--- @vararg any
|
||||||
function bait.throw(name, ...) end
|
function bait.throw(name, ...args) end
|
||||||
|
|
||||||
return bait
|
return bait
|
||||||
|
|
|
@ -8,7 +8,7 @@ function fs.abs(path) end
|
||||||
|
|
||||||
--- Gives the basename of `path`. For the rules,
|
--- Gives the basename of `path`. For the rules,
|
||||||
--- see Go's filepath.Base
|
--- see Go's filepath.Base
|
||||||
function fs.basename() end
|
function fs.basename(path) end
|
||||||
|
|
||||||
--- Changes directory to `dir`
|
--- Changes directory to `dir`
|
||||||
--- @param dir string
|
--- @param dir string
|
||||||
|
@ -16,15 +16,15 @@ function fs.cd(dir) end
|
||||||
|
|
||||||
--- Returns the directory part of `path`. For the rules, see Go's
|
--- Returns the directory part of `path`. For the rules, see Go's
|
||||||
--- filepath.Dir
|
--- filepath.Dir
|
||||||
function fs.dir() end
|
function fs.dir(path) end
|
||||||
|
|
||||||
--- Glob all files and directories that match the pattern.
|
--- Glob all files and directories that match the pattern.
|
||||||
--- For the rules, see Go's filepath.Glob
|
--- For the rules, see Go's filepath.Glob
|
||||||
function fs.glob() end
|
function fs.glob(pattern) end
|
||||||
|
|
||||||
--- Takes paths and joins them together with the OS's
|
--- Takes paths and joins them together with the OS's
|
||||||
--- directory separator (forward or backward slash).
|
--- directory separator (forward or backward slash).
|
||||||
function fs.join() end
|
function fs.join(paths...) end
|
||||||
|
|
||||||
--- Makes a directory called `name`. If `recursive` is true, it will create its parent directories.
|
--- Makes a directory called `name`. If `recursive` is true, it will create its parent directories.
|
||||||
--- @param name string
|
--- @param name string
|
||||||
|
|
|
@ -2,6 +2,38 @@
|
||||||
|
|
||||||
local hilbish = {}
|
local hilbish = {}
|
||||||
|
|
||||||
|
--- This is an alias (ha) for the `hilbish.alias` function.
|
||||||
|
--- @param alias string
|
||||||
|
--- @param cmd string
|
||||||
|
function hilbish.aliases.add(alias, cmd) end
|
||||||
|
|
||||||
|
--- This is the same as the `hilbish.runnerMode` function. It takes a callback,
|
||||||
|
--- which will be used to execute all interactive input.
|
||||||
|
--- In normal cases, neither callbacks should be overrided by the user,
|
||||||
|
--- as the higher level functions listed below this will handle it.
|
||||||
|
function hilbish.runner.setMode(cb) end
|
||||||
|
|
||||||
|
--- Calls a completer function. This is mainly used to call
|
||||||
|
--- a command completer, which will have a `name` in the form
|
||||||
|
--- of `command.name`, example: `command.git`
|
||||||
|
function hilbish.completions.call(name, query, ctx, fields) end
|
||||||
|
|
||||||
|
--- The handler function is the callback for tab completion in Hilbish.
|
||||||
|
--- You can check the completions doc for more info.
|
||||||
|
function hilbish.completions.handler(line, pos) end
|
||||||
|
|
||||||
|
--- Returns the current input line.
|
||||||
|
function hilbish.editor.getLine() end
|
||||||
|
|
||||||
|
--- Returns the text that is at the register.
|
||||||
|
function hilbish.editor.getVimRegister(register) end
|
||||||
|
|
||||||
|
--- Inserts text into the line.
|
||||||
|
function hilbish.editor.insert(text) end
|
||||||
|
|
||||||
|
--- Sets the vim register at `register` to hold the passed text.
|
||||||
|
function hilbish.editor.setVimRegister(register, text) end
|
||||||
|
|
||||||
--- Sets an alias of `cmd` to `orig`
|
--- Sets an alias of `cmd` to `orig`
|
||||||
--- @param cmd string
|
--- @param cmd string
|
||||||
--- @param orig string
|
--- @param orig string
|
||||||
|
@ -73,20 +105,21 @@ function hilbish.prependPath(dir) end
|
||||||
--- `%u` - Name of current user
|
--- `%u` - Name of current user
|
||||||
--- `%h` - Hostname of device
|
--- `%h` - Hostname of device
|
||||||
--- @param str string
|
--- @param str string
|
||||||
--- @param typ string Type of prompt, being left or right. Left by default.
|
--- @param typ string|nil Type of prompt, being left or right. Left by default.
|
||||||
function hilbish.prompt(str, typ) end
|
function hilbish.prompt(str, typ) end
|
||||||
|
|
||||||
--- Read input from the user, using Hilbish's line editor/input reader.
|
--- Read input from the user, using Hilbish's line editor/input reader.
|
||||||
--- This is a separate instance from the one Hilbish actually uses.
|
--- This is a separate instance from the one Hilbish actually uses.
|
||||||
--- Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen)
|
--- Returns `input`, will be nil if ctrl + d is pressed, or an error occurs (which shouldn't happen)
|
||||||
--- @param prompt string
|
--- @param prompt string|nil
|
||||||
|
--- @returns string|nil
|
||||||
function hilbish.read(prompt) end
|
function hilbish.read(prompt) end
|
||||||
|
|
||||||
--- Runs `cmd` in Hilbish's sh interpreter.
|
--- Runs `cmd` in Hilbish's sh interpreter.
|
||||||
--- If returnOut is true, the outputs of `cmd` will be returned as the 2nd and
|
--- If returnOut is true, the outputs of `cmd` will be returned as the 2nd and
|
||||||
--- 3rd values instead of being outputted to the terminal.
|
--- 3rd values instead of being outputted to the terminal.
|
||||||
--- @param cmd string
|
--- @param cmd string
|
||||||
function hilbish.run(cmd) end
|
function hilbish.run(cmd, returnOut) end
|
||||||
|
|
||||||
--- Sets the execution/runner mode for interactive Hilbish. This determines whether
|
--- Sets the execution/runner mode for interactive Hilbish. This determines whether
|
||||||
--- Hilbish wll try to run input as Lua and/or sh or only do one of either.
|
--- Hilbish wll try to run input as Lua and/or sh or only do one of either.
|
||||||
|
@ -105,6 +138,87 @@ function hilbish.timeout(cb, time) end
|
||||||
|
|
||||||
--- Checks if `name` is a valid command
|
--- Checks if `name` is a valid command
|
||||||
--- @param binName string
|
--- @param binName string
|
||||||
function hilbish.which(binName) end
|
function hilbish.which(name) end
|
||||||
|
|
||||||
|
--- Puts a job in the background. This acts the same as initially running a job.
|
||||||
|
function hilbish.jobs:background() end
|
||||||
|
|
||||||
|
--- Returns binary/executale completion candidates based on the provided query.
|
||||||
|
function hilbish.completions.bins(query, ctx, fields) end
|
||||||
|
|
||||||
|
--- Returns file completion candidates based on the provided query.
|
||||||
|
function hilbish.completions.files(query, ctx, fields) end
|
||||||
|
|
||||||
|
--- Puts a job in the foreground. This will cause it to run like it was
|
||||||
|
--- executed normally and wait for it to complete.
|
||||||
|
function hilbish.jobs:foreground() end
|
||||||
|
|
||||||
|
--- Evaluates `cmd` as Lua input. This is the same as using `dofile`
|
||||||
|
--- or `load`, but is appropriated for the runner interface.
|
||||||
|
function hilbish.runner.lua(cmd) end
|
||||||
|
|
||||||
|
--- Starts running the job.
|
||||||
|
function hilbish.jobs:start() end
|
||||||
|
|
||||||
|
--- Stops the job from running.
|
||||||
|
function hilbish.jobs.stop() end
|
||||||
|
|
||||||
|
--- Runs a command in Hilbish's shell script interpreter.
|
||||||
|
--- This is the equivalent of using `source`.
|
||||||
|
function hilbish.runner.sh(cmd) end
|
||||||
|
|
||||||
|
--- Starts a timer.
|
||||||
|
function hilbish.timers:start() end
|
||||||
|
|
||||||
|
--- Stops a timer.
|
||||||
|
function hilbish.timers:stop() end
|
||||||
|
|
||||||
|
--- Removes an alias.
|
||||||
|
--- @param name string
|
||||||
|
function hilbish.aliases.delete(name) end
|
||||||
|
|
||||||
|
--- Get a table of all aliases.
|
||||||
|
function hilbish.aliases.list() end
|
||||||
|
|
||||||
|
--- Tries to resolve an alias to its command.
|
||||||
|
--- @param alias string
|
||||||
|
function hilbish.aliases.resolve(alias) end
|
||||||
|
|
||||||
|
--- Adds a new job to the job table. Note that this does not immediately run it.
|
||||||
|
function hilbish.jobs.add(cmdstr, args, execPath) end
|
||||||
|
|
||||||
|
--- Returns a table of all job objects.
|
||||||
|
function hilbish.jobs.all() end
|
||||||
|
|
||||||
|
--- Disowns a job. This deletes it from the job table.
|
||||||
|
function hilbish.jobs.disown(id) end
|
||||||
|
|
||||||
|
--- Get a job object via its ID.
|
||||||
|
function hilbish.jobs.get(id) end
|
||||||
|
|
||||||
|
--- Returns the last added job from the table.
|
||||||
|
function hilbish.jobs.last() end
|
||||||
|
|
||||||
|
--- Adds a command to the history.
|
||||||
|
--- @param cmd string
|
||||||
|
function hilbish.history.add(cmd) end
|
||||||
|
|
||||||
|
--- Deletes all commands from the history.
|
||||||
|
function hilbish.history.clear() end
|
||||||
|
|
||||||
|
--- Retrieves a command from the history based on the `idx`.
|
||||||
|
--- @param idx number
|
||||||
|
function hilbish.history.get(idx) end
|
||||||
|
|
||||||
|
--- Returns the amount of commands in the history.
|
||||||
|
--- @returns number
|
||||||
|
function hilbish.history.size() end
|
||||||
|
|
||||||
|
--- Creates a timer that runs based on the specified `time` in milliseconds.
|
||||||
|
--- The `type` can either be interval (value of 0) or timeout (value of 1).
|
||||||
|
function hilbish.timers.create(type, time, callback) end
|
||||||
|
|
||||||
|
--- Retrieves a timer via its ID.
|
||||||
|
function hilbish.timers.get(id) end
|
||||||
|
|
||||||
return hilbish
|
return hilbish
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
// the event emitter
|
||||||
|
// Bait is the event emitter for Hilbish. Why name it bait? Why not.
|
||||||
|
// It throws hooks that you can catch. This is what you will use if
|
||||||
|
// you want to listen in on hooks to know when certain things have
|
||||||
|
// happened, like when you've changed directory, a command has failed,
|
||||||
|
// etc. To find all available hooks thrown by Hilbish, see doc hooks.
|
||||||
package bait
|
package bait
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// library for custom commands
|
||||||
|
// Commander is a library for writing custom commands in Lua.
|
||||||
package commander
|
package commander
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// filesystem interaction and functionality library
|
||||||
|
// The fs module provides easy and simple access to filesystem functions
|
||||||
|
// and other things, and acts an addition to the Lua standard library's
|
||||||
|
// I/O and filesystem functions.
|
||||||
package fs
|
package fs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// low level terminal library
|
||||||
|
// The terminal library is a simple and lower level library for certain terminal interactions.
|
||||||
package terminal
|
package terminal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
45
job.go
45
job.go
|
@ -110,6 +110,10 @@ func (j *job) getProc() *os.Process {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface jobs
|
||||||
|
// #member
|
||||||
|
// start()
|
||||||
|
// Starts running the job.
|
||||||
func luaStartJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func luaStartJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -130,6 +134,9 @@ func luaStartJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface jobs
|
||||||
|
// stop()
|
||||||
|
// Stops the job from running.
|
||||||
func luaStopJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func luaStopJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -148,6 +155,11 @@ func luaStopJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface jobs
|
||||||
|
// #member
|
||||||
|
// foreground()
|
||||||
|
// Puts a job in the foreground. This will cause it to run like it was
|
||||||
|
// executed normally and wait for it to complete.
|
||||||
func luaForegroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func luaForegroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -180,6 +192,10 @@ func luaForegroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface jobs
|
||||||
|
// #member
|
||||||
|
// background()
|
||||||
|
// Puts a job in the background. This acts the same as initially running a job.
|
||||||
func luaBackgroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func luaBackgroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -276,6 +292,20 @@ func (j *jobHandler) stopAll() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #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
|
||||||
|
/*
|
||||||
|
Manage interactive jobs in Hilbish via Lua.
|
||||||
|
|
||||||
|
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. */
|
||||||
func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table {
|
func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table {
|
||||||
jobMethods := rt.NewTable()
|
jobMethods := rt.NewTable()
|
||||||
jFuncs := map[string]util.LuaExport{
|
jFuncs := map[string]util.LuaExport{
|
||||||
|
@ -353,6 +383,9 @@ func jobUserData(j *job) *rt.UserData {
|
||||||
return rt.NewUserData(j, jobMeta.AsTable())
|
return rt.NewUserData(j, jobMeta.AsTable())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface jobs
|
||||||
|
// get(id)
|
||||||
|
// Get a job object via its ID.
|
||||||
func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
j.mu.RLock()
|
j.mu.RLock()
|
||||||
defer j.mu.RUnlock()
|
defer j.mu.RUnlock()
|
||||||
|
@ -373,6 +406,9 @@ func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.PushingNext(t.Runtime, rt.UserDataValue(job.ud)), nil
|
return c.PushingNext(t.Runtime, rt.UserDataValue(job.ud)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface jobs
|
||||||
|
// add(cmdstr, args, execPath)
|
||||||
|
// Adds a new job to the job table. Note that this does not immediately run it.
|
||||||
func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.CheckNArgs(3); err != nil {
|
if err := c.CheckNArgs(3); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -402,6 +438,9 @@ func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.PushingNext1(t.Runtime, rt.UserDataValue(jb.ud)), nil
|
return c.PushingNext1(t.Runtime, rt.UserDataValue(jb.ud)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface jobs
|
||||||
|
// all()
|
||||||
|
// Returns a table of all job objects.
|
||||||
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) {
|
||||||
j.mu.RLock()
|
j.mu.RLock()
|
||||||
defer j.mu.RUnlock()
|
defer j.mu.RUnlock()
|
||||||
|
@ -414,6 +453,9 @@ func (j *jobHandler) luaAllJobs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.PushingNext1(t.Runtime, rt.TableValue(jobTbl)), nil
|
return c.PushingNext1(t.Runtime, rt.TableValue(jobTbl)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface jobs
|
||||||
|
// disown(id)
|
||||||
|
// Disowns a job. This deletes it from the job table.
|
||||||
func (j *jobHandler) luaDisownJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (j *jobHandler) luaDisownJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -431,6 +473,9 @@ func (j *jobHandler) luaDisownJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface jobs
|
||||||
|
// last() -> Job
|
||||||
|
// Returns the last added job from the table.
|
||||||
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) {
|
||||||
j.mu.RLock()
|
j.mu.RLock()
|
||||||
defer j.mu.RUnlock()
|
defer j.mu.RUnlock()
|
||||||
|
|
|
@ -4,34 +4,34 @@ local lunacolors = require 'lunacolors'
|
||||||
|
|
||||||
commander.register('doc', function(args)
|
commander.register('doc', function(args)
|
||||||
local moddocPath = hilbish.dataDir .. '/docs/'
|
local moddocPath = hilbish.dataDir .. '/docs/'
|
||||||
local modDocFormat = [[
|
local apidocHeader = [[
|
||||||
%s
|
# %s
|
||||||
%s
|
{grayBg} {white}{italic}%s {reset}
|
||||||
# Functions
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
if #args > 0 then
|
if #args > 0 then
|
||||||
local mod = args[1]
|
local mod = args[1]
|
||||||
|
|
||||||
local f = io.open(moddocPath .. mod .. '.txt', 'rb')
|
local f = io.open(moddocPath .. mod .. '.md', 'rb')
|
||||||
local funcdocs = nil
|
local funcdocs = nil
|
||||||
if not f then
|
if not f then
|
||||||
-- assume subdir
|
-- assume subdir
|
||||||
-- dataDir/docs/<mod>/<mod>.txt
|
-- dataDir/docs/<mod>/<mod>.md
|
||||||
moddocPath = moddocPath .. mod .. '/'
|
moddocPath = moddocPath .. mod .. '/'
|
||||||
local subdocName = args[2]
|
local subdocName = args[2]
|
||||||
if not subdocName then
|
if not subdocName then
|
||||||
subdocName = 'index'
|
subdocName = 'index'
|
||||||
end
|
end
|
||||||
f = io.open(moddocPath .. subdocName .. '.txt', 'rb')
|
f = io.open(moddocPath .. subdocName .. '.md', 'rb')
|
||||||
if not f then
|
if not f then
|
||||||
print('No documentation found for ' .. mod .. '.')
|
print('No documentation found for ' .. mod .. '.')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
funcdocs = f:read '*a'
|
funcdocs = f:read '*a'
|
||||||
local moddocs = table.filter(fs.readdir(moddocPath), function(f) return f ~= 'index.txt' end)
|
local moddocs = table.filter(fs.readdir(moddocPath), function(f) return f ~= 'index.md' end)
|
||||||
local subdocs = table.map(moddocs, function(fname)
|
local subdocs = table.map(moddocs, function(fname)
|
||||||
return lunacolors.underline(lunacolors.blue(string.gsub(fname, '.txt', '')))
|
return lunacolors.underline(lunacolors.blue(string.gsub(fname, '.md', '')))
|
||||||
end)
|
end)
|
||||||
if subdocName == 'index' then
|
if subdocName == 'index' then
|
||||||
funcdocs = funcdocs .. '\nSubdocs: ' .. table.concat(subdocs, ', ')
|
funcdocs = funcdocs .. '\nSubdocs: ' .. table.concat(subdocs, ', ')
|
||||||
|
@ -41,8 +41,24 @@ commander.register('doc', function(args)
|
||||||
if not funcdocs then
|
if not funcdocs then
|
||||||
funcdocs = f:read '*a'
|
funcdocs = f:read '*a'
|
||||||
end
|
end
|
||||||
local desc = ''
|
local valsStr = funcdocs:match '%-%-%-\n([^%-%-%-]+)\n'
|
||||||
local ok = pcall(require, mod)
|
local vals = {}
|
||||||
|
if valsStr then
|
||||||
|
local _, endpos = funcdocs:find('---\n' .. valsStr .. '\n---\n\n', 1, true)
|
||||||
|
funcdocs = funcdocs:sub(endpos + 1, #funcdocs)
|
||||||
|
|
||||||
|
-- parse vals
|
||||||
|
local lines = string.split(valsStr, '\n')
|
||||||
|
for _, line in ipairs(lines) do
|
||||||
|
local key = line:match '(%w+): '
|
||||||
|
local val = line:match '^%w+: (.-)$'
|
||||||
|
|
||||||
|
vals[key] = val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if mod == 'api' then
|
||||||
|
funcdocs = string.format(apidocHeader, vals.name, vals.description) .. funcdocs
|
||||||
|
end
|
||||||
local backtickOccurence = 0
|
local backtickOccurence = 0
|
||||||
local formattedFuncs = lunacolors.format(funcdocs:sub(1, #funcdocs - 1):gsub('`', function()
|
local formattedFuncs = lunacolors.format(funcdocs:sub(1, #funcdocs - 1):gsub('`', function()
|
||||||
backtickOccurence = backtickOccurence + 1
|
backtickOccurence = backtickOccurence + 1
|
||||||
|
@ -51,34 +67,16 @@ commander.register('doc', function(args)
|
||||||
else
|
else
|
||||||
return '{underline}{green}'
|
return '{underline}{green}'
|
||||||
end
|
end
|
||||||
|
end):gsub('#+.-\n', function(t)
|
||||||
|
return '{bold}{magenta}' .. t .. '{reset}'
|
||||||
end))
|
end))
|
||||||
|
print(formattedFuncs)
|
||||||
if ok then
|
|
||||||
local props = {}
|
|
||||||
local propstr = ''
|
|
||||||
local modDesc = ''
|
|
||||||
local modmt = getmetatable(require(mod))
|
|
||||||
if modmt then
|
|
||||||
modDesc = modmt.__doc
|
|
||||||
if modmt.__docProp then
|
|
||||||
-- not all modules have docs for properties
|
|
||||||
props = table.map(modmt.__docProp, function(v, k)
|
|
||||||
return lunacolors.underline(lunacolors.blue(k)) .. ' > ' .. v
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
if #props > 0 then
|
|
||||||
propstr = '\n# Properties\n' .. table.concat(props, '\n') .. '\n'
|
|
||||||
end
|
|
||||||
desc = string.format(modDocFormat, modDesc, propstr)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
print(desc .. formattedFuncs)
|
|
||||||
f:close()
|
f:close()
|
||||||
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local modules = table.map(fs.readdir(moddocPath), function(f)
|
local modules = table.map(fs.readdir(moddocPath), function(f)
|
||||||
return lunacolors.underline(lunacolors.blue(string.gsub(f, '.txt', '')))
|
return lunacolors.underline(lunacolors.blue(string.gsub(f, '.md', '')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
io.write [[
|
io.write [[
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
--- hilbish.runner
|
||||||
local currentRunner = 'hybrid'
|
local currentRunner = 'hybrid'
|
||||||
local runners = {}
|
local runners = {}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"hilbish/util"
|
||||||
|
|
||||||
|
rt "github.com/arnodel/golua/runtime"
|
||||||
|
"github.com/blackfireio/osinfo"
|
||||||
|
)
|
||||||
|
|
||||||
|
// #interface os
|
||||||
|
// OS Info
|
||||||
|
// The `os` interface provides simple text information properties about
|
||||||
|
// the current OS on the systen. This mainly includes the name and
|
||||||
|
// version.
|
||||||
|
// #field family Family name of the current OS
|
||||||
|
// #field name Pretty name of the current OS
|
||||||
|
// #field version Version of the current OS
|
||||||
|
func hshosLoader(rtm *rt.Runtime) *rt.Table {
|
||||||
|
info, _ := osinfo.GetOSInfo()
|
||||||
|
mod := rt.NewTable()
|
||||||
|
|
||||||
|
util.SetField(rtm, mod, "family", rt.StringValue(info.Family), "Family name of the current OS")
|
||||||
|
util.SetField(rtm, mod, "name", rt.StringValue(info.Name), "Pretty name of the current OS")
|
||||||
|
util.SetField(rtm, mod, "version", rt.StringValue(info.Version), "Version of the current OS")
|
||||||
|
|
||||||
|
return mod
|
||||||
|
}
|
21
rl.go
21
rl.go
|
@ -225,7 +225,11 @@ func (lr *lineReader) Resize() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// lua module
|
// #interface history
|
||||||
|
// command history
|
||||||
|
// The history interface deals with command history.
|
||||||
|
// This includes the ability to override functions to change the main
|
||||||
|
// method of saving history.
|
||||||
func (lr *lineReader) Loader(rtm *rt.Runtime) *rt.Table {
|
func (lr *lineReader) Loader(rtm *rt.Runtime) *rt.Table {
|
||||||
lrLua := map[string]util.LuaExport{
|
lrLua := map[string]util.LuaExport{
|
||||||
"add": {lr.luaAddHistory, 1, false},
|
"add": {lr.luaAddHistory, 1, false},
|
||||||
|
@ -241,6 +245,10 @@ func (lr *lineReader) Loader(rtm *rt.Runtime) *rt.Table {
|
||||||
return mod
|
return mod
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface history
|
||||||
|
// add(cmd)
|
||||||
|
// Adds a command to the history.
|
||||||
|
// --- @param cmd string
|
||||||
func (lr *lineReader) luaAddHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (lr *lineReader) luaAddHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -254,10 +262,18 @@ func (lr *lineReader) luaAddHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error)
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface history
|
||||||
|
// size()
|
||||||
|
// Returns the amount of commands in the history.
|
||||||
|
// --- @returns number
|
||||||
func (lr *lineReader) luaSize(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (lr *lineReader) luaSize(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.PushingNext1(t.Runtime, rt.IntValue(int64(lr.fileHist.Len()))), nil
|
return c.PushingNext1(t.Runtime, rt.IntValue(int64(lr.fileHist.Len()))), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface history
|
||||||
|
// get(idx)
|
||||||
|
// Retrieves a command from the history based on the `idx`.
|
||||||
|
// --- @param idx number
|
||||||
func (lr *lineReader) luaGetHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (lr *lineReader) luaGetHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -284,6 +300,9 @@ func (lr *lineReader) luaAllHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error)
|
||||||
return c.PushingNext1(t.Runtime, rt.TableValue(tbl)), nil
|
return c.PushingNext1(t.Runtime, rt.TableValue(tbl)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface history
|
||||||
|
// clear()
|
||||||
|
// Deletes all commands from the history.
|
||||||
func (lr *lineReader) luaClearHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func (lr *lineReader) luaClearHistory(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
lr.fileHist.clear()
|
lr.fileHist.clear()
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
|
|
|
@ -6,6 +6,13 @@ import (
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// #interface runner
|
||||||
|
// interactive command runner customization
|
||||||
|
// The runner interface contains functions that allow the user to change
|
||||||
|
// how Hilbish interprets interactive input.
|
||||||
|
// Users can add and change the default runner for interactive input to any
|
||||||
|
// language or script of their choosing. A good example is using it to
|
||||||
|
// write command in Fennel.
|
||||||
func runnerModeLoader(rtm *rt.Runtime) *rt.Table {
|
func runnerModeLoader(rtm *rt.Runtime) *rt.Table {
|
||||||
exports := map[string]util.LuaExport{
|
exports := map[string]util.LuaExport{
|
||||||
"sh": {shRunner, 1, false},
|
"sh": {shRunner, 1, false},
|
||||||
|
@ -19,6 +26,18 @@ func runnerModeLoader(rtm *rt.Runtime) *rt.Table {
|
||||||
return mod
|
return mod
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface runner
|
||||||
|
// setMode(cb)
|
||||||
|
// This is the same as the `hilbish.runnerMode` function. It takes a callback,
|
||||||
|
// which will be used to execute all interactive input.
|
||||||
|
// In normal cases, neither callbacks should be overrided by the user,
|
||||||
|
// as the higher level functions listed below this will handle it.
|
||||||
|
func _runnerMode() {}
|
||||||
|
|
||||||
|
// #interface runner
|
||||||
|
// sh(cmd)
|
||||||
|
// Runs a command in Hilbish's shell script interpreter.
|
||||||
|
// This is the equivalent of using `source`.
|
||||||
func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -42,6 +61,10 @@ func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.PushingNext(t.Runtime, rt.TableValue(runnerRet)), nil
|
return c.PushingNext(t.Runtime, rt.TableValue(runnerRet)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface runner
|
||||||
|
// lua(cmd)
|
||||||
|
// Evaluates `cmd` as Lua input. This is the same as using `dofile`
|
||||||
|
// or `load`, but is appropriated for the runner interface.
|
||||||
func luaRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func luaRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
10
timer.go
10
timer.go
|
@ -21,7 +21,7 @@ type timer struct{
|
||||||
running bool
|
running bool
|
||||||
dur time.Duration
|
dur time.Duration
|
||||||
fun *rt.Closure
|
fun *rt.Closure
|
||||||
th *timerHandler
|
th *timersModule
|
||||||
ticker *time.Ticker
|
ticker *time.Ticker
|
||||||
ud *rt.UserData
|
ud *rt.UserData
|
||||||
channel chan struct{}
|
channel chan struct{}
|
||||||
|
@ -73,6 +73,10 @@ func (t *timer) stop() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface timers
|
||||||
|
// #member
|
||||||
|
// start()
|
||||||
|
// Starts a timer.
|
||||||
func timerStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func timerStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -91,6 +95,10 @@ func timerStart(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #interface timers
|
||||||
|
// #member
|
||||||
|
// stop()
|
||||||
|
// Stops a timer.
|
||||||
func timerStop(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func timerStop(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -10,10 +10,10 @@ import (
|
||||||
rt "github.com/arnodel/golua/runtime"
|
rt "github.com/arnodel/golua/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
var timers *timerHandler
|
var timers *timersModule
|
||||||
var timerMetaKey = rt.StringValue("hshtimer")
|
var timerMetaKey = rt.StringValue("hshtimer")
|
||||||
|
|
||||||
type timerHandler struct {
|
type timersModule struct {
|
||||||
mu *sync.RWMutex
|
mu *sync.RWMutex
|
||||||
wg *sync.WaitGroup
|
wg *sync.WaitGroup
|
||||||
timers map[int]*timer
|
timers map[int]*timer
|
||||||
|
@ -21,8 +21,8 @@ type timerHandler struct {
|
||||||
running int
|
running int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTimerHandler() *timerHandler {
|
func newTimersModule() *timersModule {
|
||||||
return &timerHandler{
|
return &timersModule{
|
||||||
timers: make(map[int]*timer),
|
timers: make(map[int]*timer),
|
||||||
latestID: 0,
|
latestID: 0,
|
||||||
mu: &sync.RWMutex{},
|
mu: &sync.RWMutex{},
|
||||||
|
@ -30,11 +30,11 @@ func newTimerHandler() *timerHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (th *timerHandler) wait() {
|
func (th *timersModule) wait() {
|
||||||
th.wg.Wait()
|
th.wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (th *timerHandler) create(typ timerType, dur time.Duration, fun *rt.Closure) *timer {
|
func (th *timersModule) create(typ timerType, dur time.Duration, fun *rt.Closure) *timer {
|
||||||
th.mu.Lock()
|
th.mu.Lock()
|
||||||
defer th.mu.Unlock()
|
defer th.mu.Unlock()
|
||||||
|
|
||||||
|
@ -54,14 +54,18 @@ func (th *timerHandler) create(typ timerType, dur time.Duration, fun *rt.Closure
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (th *timerHandler) get(id int) *timer {
|
func (th *timersModule) get(id int) *timer {
|
||||||
th.mu.RLock()
|
th.mu.RLock()
|
||||||
defer th.mu.RUnlock()
|
defer th.mu.RUnlock()
|
||||||
|
|
||||||
return th.timers[id]
|
return th.timers[id]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (th *timerHandler) luaCreate(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
// #interface timers
|
||||||
|
// create(type, time, callback)
|
||||||
|
// Creates a timer that runs based on the specified `time` in milliseconds.
|
||||||
|
// The `type` can either be interval (value of 0) or timeout (value of 1).
|
||||||
|
func (th *timersModule) luaCreate(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.CheckNArgs(3); err != nil {
|
if err := c.CheckNArgs(3); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -83,7 +87,10 @@ func (th *timerHandler) luaCreate(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.PushingNext1(t.Runtime, rt.UserDataValue(tmr.ud)), nil
|
return c.PushingNext1(t.Runtime, rt.UserDataValue(tmr.ud)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (th *timerHandler) luaGet(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
// #interface timers
|
||||||
|
// get(id)
|
||||||
|
// Retrieves a timer via its ID.
|
||||||
|
func (th *timersModule) luaGet(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -100,7 +107,15 @@ func (th *timerHandler) luaGet(thr *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (th *timerHandler) loader(rtm *rt.Runtime) *rt.Table {
|
// #interface timers
|
||||||
|
// #property type What type of timer it is
|
||||||
|
// #property running If the timer is running
|
||||||
|
// #property duration The duration in milliseconds that the timer will run
|
||||||
|
// timeout and interval API
|
||||||
|
// The timers interface si one to easily set timeouts and intervals
|
||||||
|
// to run functions after a certain time or repeatedly without using
|
||||||
|
// odd tricks.
|
||||||
|
func (th *timersModule) loader(rtm *rt.Runtime) *rt.Table {
|
||||||
timerMethods := rt.NewTable()
|
timerMethods := rt.NewTable()
|
||||||
timerFuncs := map[string]util.LuaExport{
|
timerFuncs := map[string]util.LuaExport{
|
||||||
"start": {timerStart, 1, false},
|
"start": {timerStart, 1, false},
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"hilbish/util"
|
||||||
|
|
||||||
|
rt "github.com/arnodel/golua/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// #interface userDir
|
||||||
|
// user-related directories
|
||||||
|
// This interface just contains properties to know about certain user directories.
|
||||||
|
// It is equivalent to XDG on Linux and gets the user's preferred directories
|
||||||
|
// for configs and data.
|
||||||
|
// #field config The user's config directory
|
||||||
|
// #field data The user's directory for program data
|
||||||
|
func userDirLoader(rtm *rt.Runtime) *rt.Table {
|
||||||
|
mod := rt.NewTable()
|
||||||
|
|
||||||
|
util.SetField(rtm, mod, "config", rt.StringValue(confDir), "User's config directory")
|
||||||
|
util.SetField(rtm, mod, "data", rt.StringValue(userDataDir), "XDG data directory")
|
||||||
|
|
||||||
|
return mod
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
../../../docs/api/
|
Loading…
Reference in New Issue