mirror of https://github.com/Hilbis/Hilbish
Compare commits
27 Commits
37d8b944e9
...
79a24cc2b4
Author | SHA1 | Date |
---|---|---|
sammyette | 79a24cc2b4 | |
sammyette | d37e036d1f | |
sammyette | b54b84f2b3 | |
sammyette | 4e8e6d7ccf | |
sammyette | 388078a38d | |
sammyette | 51558c5a05 | |
sammyette | 6f95ae6564 | |
sammyette | 0ba0dead53 | |
sammyette | fd359fd525 | |
sammyette | fc82d4f5eb | |
sammyette | e5eefb1d2d | |
sammyette | 6525fa774e | |
sammyette | 514cbe25c7 | |
sammyette | 84dd939bbf | |
sammyette | f94b8ae59b | |
sammyette | 7b3dc951c9 | |
sammyette | 0a49e1a4ef | |
TorchedSammy | 6ca36847f1 | |
TorchedSammy | 5ca728ba06 | |
sammyette | 813354b662 | |
TorchedSammy | 8d40179a73 | |
TorchedSammy | f7e725b5b9 | |
sammyette | 4ee160fb66 | |
TorchedSammy | 1024f93446 | |
TorchedSammy | 9c8d7692bc | |
TorchedSammy | 9131c72501 | |
TorchedSammy | 26ff6c9a46 |
|
@ -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
|
||||||
|
|
|
@ -33,6 +33,7 @@ jobs:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
fetch-depth: 0
|
||||||
- name: Download Task
|
- name: Download Task
|
||||||
run: 'sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d'
|
run: 'sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d'
|
||||||
- uses: wangyoucao577/go-release-action@v1.25
|
- uses: wangyoucao577/go-release-action@v1.25
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
name: Build website
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- docs-refactor
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Setup Hugo
|
||||||
|
uses: peaceiris/actions-hugo@v2
|
||||||
|
with:
|
||||||
|
hugo-version: 'latest'
|
||||||
|
extended: true
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: 'cd website && hugo --minify'
|
||||||
|
|
||||||
|
- name: Deploy
|
||||||
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
publish_dir: ./website/public
|
|
@ -1,6 +1,8 @@
|
||||||
*.exe
|
*.exe
|
||||||
hilbish
|
hilbish
|
||||||
|
!docs/api/hilbish
|
||||||
docgen
|
docgen
|
||||||
|
!cmd/docgen
|
||||||
|
|
||||||
.vim
|
.vim
|
||||||
petals/
|
petals/
|
||||||
|
|
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -1,9 +1,16 @@
|
||||||
# 🎀 Changelog
|
# 🎀 Changelog
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
**NOTE:** Hilbish now uses [Task] insead of Make for builds.
|
**NOTES FOR USERS/PACKAGERS UPDATING:**
|
||||||
Windows support is also now at a lower tier; The only thing guaranteed is
|
- Hilbish now uses [Task] insead of Make for builds.
|
||||||
Hilbish *compiling* on Windows.
|
- The doc format has been changed from plain text to markdown.
|
||||||
|
**YOU MUST reinstall Hilbish to remove the duplicate, old docs.**
|
||||||
|
- Hilbish will by default install to **`/usr/local`** instead of just `/usr/`
|
||||||
|
when building via Task. This is mainly to avoid conflict of distro packages
|
||||||
|
and local installs, and is the correct place when building from git either way.
|
||||||
|
To keep Hilbish in `/usr`, you must have `PREFIX="/usr/"` when running `task build` or `task install`
|
||||||
|
- Windows is no longer supported. It will build and run, but **will** have problems.
|
||||||
|
If you want to help fix the situation, start a discussion or open an issue and contribute.
|
||||||
|
|
||||||
[Task]: https://taskfile.dev/#/
|
[Task]: https://taskfile.dev/#/
|
||||||
|
|
||||||
|
@ -103,6 +110,7 @@ of a dot. (ie. `job.stop()` -> `job:stop()`)
|
||||||
- All `fs` module functions which take paths now implicitly expand ~ to home.
|
- All `fs` module functions which take paths now implicitly expand ~ to home.
|
||||||
- **Breaking Change:** `hilbish.greeting` has been moved to an opt (`hilbish.opts.greeting`) and is
|
- **Breaking Change:** `hilbish.greeting` has been moved to an opt (`hilbish.opts.greeting`) and is
|
||||||
always printed by default. To disable it, set the opt to false.
|
always printed by default. To disable it, set the opt to false.
|
||||||
|
- **Breaking Change:** `command.no-perm` hook has been replaced with `command.not-executable`
|
||||||
- History is now fetched from Lua, which means users can override `hilbish.history`
|
- History is now fetched from Lua, which means users can override `hilbish.history`
|
||||||
methods to make it act how they want.
|
methods to make it act how they want.
|
||||||
- `guide` has been removed. See the [website](https://rosettea.github.io/Hilbish/)
|
- `guide` has been removed. See the [website](https://rosettea.github.io/Hilbish/)
|
||||||
|
@ -161,6 +169,8 @@ will result in the files being completed.
|
||||||
- Cut off item names in grid menu if its longer than cell width
|
- Cut off item names in grid menu if its longer than cell width
|
||||||
- Fix completion search menu disappearing
|
- Fix completion search menu disappearing
|
||||||
- Completion paths having duplicated characters if it's escaped
|
- Completion paths having duplicated characters if it's escaped
|
||||||
|
- Get custom completion command properly to call from Lua
|
||||||
|
- Put proper command on the line when using up and down arrow keys to go through command history
|
||||||
|
|
||||||
## [2.0.0-rc1] - 2022-09-14
|
## [2.0.0-rc1] - 2022-09-14
|
||||||
This is a pre-release version of Hilbish for testing. To see the changelog,
|
This is a pre-release version of Hilbish for testing. To see the changelog,
|
||||||
|
|
|
@ -69,7 +69,7 @@ If you're new to nix you should probably read up on how to do that [here](https:
|
||||||
## Manual Build
|
## Manual Build
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
- [Go 1.17+](https://go.dev)
|
- [Go 1.17+](https://go.dev)
|
||||||
- [Task](https://taskfile.dev/#/)
|
- [Task](https://taskfile.dev/installation/) (**Go on the hyperlink here to see Task's install method for your OS.**)
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
First, clone Hilbish. The recursive is required, as some Lua libraries
|
First, clone Hilbish. The recursive is required, as some Lua libraries
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
vars:
|
vars:
|
||||||
PREFIX: '{{default "/usr" .PREFIX}}'
|
PREFIX: '{{default "/usr/local" .PREFIX}}'
|
||||||
bindir__: '{{.PREFIX}}/bin'
|
bindir__: '{{.PREFIX}}/bin'
|
||||||
BINDIR: '{{default .bindir__ .BINDIR}}'
|
BINDIR: '{{default .bindir__ .BINDIR}}'
|
||||||
libdir__: '{{.PREFIX}}/share/hilbish'
|
libdir__: '{{.PREFIX}}/share/hilbish'
|
||||||
LIBDIR: '{{default .libdir__ .LIBDIR}}'
|
LIBDIR: '{{default .libdir__ .LIBDIR}}'
|
||||||
goflags__: '-ldflags "-s -w"'
|
goflags__: '-ldflags "-s -w -X main.dataDir={{.LIBDIR}}"'
|
||||||
GOFLAGS: '{{default .goflags__ .GOFLAGS}}'
|
GOFLAGS: '{{default .goflags__ .GOFLAGS}}'
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
|
@ -16,7 +16,7 @@ tasks:
|
||||||
cmds:
|
cmds:
|
||||||
- CGO_ENABLED=0 go build {{.GOFLAGS}}
|
- CGO_ENABLED=0 go build {{.GOFLAGS}}
|
||||||
vars:
|
vars:
|
||||||
GOFLAGS: '-ldflags "-s -w -X main.gitCommit=$(git rev-parse --short HEAD) -X main.gitBranch=$(git rev-parse --abbrev-ref HEAD)"'
|
GOFLAGS: '-ldflags "-s -w -X main.dataDir={{.LIBDIR}} -X main.gitCommit=$(git rev-parse --short HEAD) -X main.gitBranch=$(git rev-parse --abbrev-ref HEAD)"'
|
||||||
|
|
||||||
build:
|
build:
|
||||||
cmds:
|
cmds:
|
||||||
|
|
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,27 +9,192 @@ 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 {
|
||||||
if !info.IsDir() {
|
if !info.IsDir() {
|
||||||
|
@ -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")
|
if v.ParentModule != "" {
|
||||||
}
|
docPath = "docs/api/" + v.ParentModule + "/" + mod + ".md"
|
||||||
}
|
|
||||||
f.WriteString("\n")
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for mod, v := range emmyDocs {
|
go func(modname, docPath string, modu module) {
|
||||||
if mod == "main" { continue }
|
defer wg.Done()
|
||||||
f, _ := os.Create("emmyLuaDocs/" + mod + ".lua")
|
modOrIface := "Module"
|
||||||
f.WriteString("--- @meta\n\nlocal " + mod + " = {}\n\n")
|
if modu.ParentModule != "" {
|
||||||
for _, em := range v {
|
modOrIface = "Interface"
|
||||||
var funcdocs []string
|
}
|
||||||
for _, dps := range docs[mod] {
|
|
||||||
if dps.FuncName == em.FuncName {
|
f, _ := os.Create(docPath)
|
||||||
funcdocs = dps.Doc
|
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")
|
||||||
}
|
}
|
||||||
f.WriteString("--- " + strings.Join(funcdocs, "\n--- ") + "\n")
|
if len(modu.Properties) != 0 {
|
||||||
if len(em.Docs) != 0 {
|
f.WriteString("## Object properties\n")
|
||||||
f.WriteString(strings.Join(em.Docs, "\n") + "\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")
|
||||||
}
|
}
|
||||||
f.WriteString("function " + mod + "." + em.FuncName + "(" + strings.Join(em.Params, ", ") + ") end\n\n")
|
if len(modu.Docs) != 0 {
|
||||||
}
|
f.WriteString("## Functions\n")
|
||||||
f.WriteString("return " + mod + "\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
|
||||||
|
|
4
exec.go
4
exec.go
|
@ -141,9 +141,9 @@ func runInput(input string, priv bool) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if exErr, ok := isExecError(err); ok {
|
if exErr, ok := isExecError(err); ok {
|
||||||
hooks.Emit("command." + exErr.typ, exErr.cmd)
|
hooks.Emit("command." + exErr.typ, exErr.cmd)
|
||||||
err = exErr.sprint()
|
} else {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
}
|
}
|
||||||
fmt.Fprintln(os.Stderr, err)
|
|
||||||
}
|
}
|
||||||
cmdFinish(exitCode, input, priv)
|
cmdFinish(exitCode, input, priv)
|
||||||
}
|
}
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -29,4 +29,4 @@ replace github.com/maxlandon/readline => ./readline
|
||||||
|
|
||||||
replace layeh.com/gopher-luar => github.com/layeh/gopher-luar v1.0.10
|
replace layeh.com/gopher-luar => github.com/layeh/gopher-luar v1.0.10
|
||||||
|
|
||||||
replace github.com/arnodel/golua => github.com/Rosettea/golua v0.0.0-20220518005949-116371948fe3
|
replace github.com/arnodel/golua => github.com/Rosettea/golua v0.0.0-20221213193027-cbf6d4e4d345
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -2,6 +2,10 @@ github.com/Rosettea/golua v0.0.0-20220419183026-6d22d6fec5ac h1:dtXrgjch8PQyf7C9
|
||||||
github.com/Rosettea/golua v0.0.0-20220419183026-6d22d6fec5ac/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
|
github.com/Rosettea/golua v0.0.0-20220419183026-6d22d6fec5ac/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
|
||||||
github.com/Rosettea/golua v0.0.0-20220518005949-116371948fe3 h1:I/wWr40FFLFF9pbT3wLb1FAEZhKb/hUWE+nJ5uHBK2g=
|
github.com/Rosettea/golua v0.0.0-20220518005949-116371948fe3 h1:I/wWr40FFLFF9pbT3wLb1FAEZhKb/hUWE+nJ5uHBK2g=
|
||||||
github.com/Rosettea/golua v0.0.0-20220518005949-116371948fe3/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
|
github.com/Rosettea/golua v0.0.0-20220518005949-116371948fe3/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
|
||||||
|
github.com/Rosettea/golua v0.0.0-20220621002945-b05143999437 h1:6lWu4YVLeKuZ8jR9xwHONhkHBsrIbw5dpfG1gtOVw0A=
|
||||||
|
github.com/Rosettea/golua v0.0.0-20220621002945-b05143999437/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
|
||||||
|
github.com/Rosettea/golua v0.0.0-20221213193027-cbf6d4e4d345 h1:QNYjYDogUSiNUkffbhFSrSCtpZhofeiVYGFN2FI4wSs=
|
||||||
|
github.com/Rosettea/golua v0.0.0-20221213193027-cbf6d4e4d345/go.mod h1:9jzpYPiU2is0HVGCiuIOBSXdergHUW44IEjmuN1UrIE=
|
||||||
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220306140409-795a84b00b4e h1:P2XupP8SaylWaudD1DqbWtZ3mIa8OsE9635LmR+Q+lg=
|
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220306140409-795a84b00b4e h1:P2XupP8SaylWaudD1DqbWtZ3mIa8OsE9635LmR+Q+lg=
|
||||||
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220306140409-795a84b00b4e/go.mod h1:R09vh/04ILvP2Gj8/Z9Jd0Dh0ZIvaucowMEs6abQpWs=
|
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220306140409-795a84b00b4e/go.mod h1:R09vh/04ILvP2Gj8/Z9Jd0Dh0ZIvaucowMEs6abQpWs=
|
||||||
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220524215627-dfd9a4fa219b h1:s5eDMhBk6H1BgipgLub/gv9qeyBaTuiHM0k3h2/9TSE=
|
github.com/Rosettea/sh/v3 v3.4.0-0.dev.0.20220524215627-dfd9a4fa219b h1:s5eDMhBk6H1BgipgLub/gv9qeyBaTuiHM0k3h2/9TSE=
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
%global debug_package %{nil}
|
%global debug_package %{nil}
|
||||||
|
|
||||||
Name: hilbish-git
|
Name: hilbish-git
|
||||||
Version: {{{ git_dir_version }}}
|
Version: {{{ git_tag_version }}}.{{{ git_short_hash }}}
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: The flower shell. A comfy and nice little shell for Lua fans!
|
Summary: The flower shell. A comfy and nice little shell for Lua fans!
|
||||||
License: MIT
|
License: MIT
|
||||||
|
|
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 [[
|
||||||
|
|
|
@ -24,7 +24,7 @@ function hilbish.completion.handler(line, pos)
|
||||||
return {compGroup}, pfx
|
return {compGroup}, pfx
|
||||||
else
|
else
|
||||||
local ok, compGroups, pfx = pcall(hilbish.completion.call,
|
local ok, compGroups, pfx = pcall(hilbish.completion.call,
|
||||||
'command.' .. #fields[1], query, ctx, fields)
|
'command.' .. fields[1], query, ctx, fields)
|
||||||
if ok then
|
if ok then
|
||||||
return compGroups, pfx
|
return compGroups, pfx
|
||||||
end
|
end
|
||||||
|
|
|
@ -69,3 +69,11 @@ end
|
||||||
bait.catch('error', function(event, handler, err)
|
bait.catch('error', function(event, handler, err)
|
||||||
bait.release(event, handler)
|
bait.release(event, handler)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
bait.catch('command.not-found', function(cmd)
|
||||||
|
print(string.format('hilbish: %s not found', cmd))
|
||||||
|
end)
|
||||||
|
|
||||||
|
bait.catch('command.not-executable', function(cmd)
|
||||||
|
print(string.format('hilbish: %s: not executable', cmd))
|
||||||
|
end)
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -123,23 +123,20 @@ func (rl *Instance) walkHistory(i int) {
|
||||||
|
|
||||||
// When we are exiting the current line buffer to move around
|
// When we are exiting the current line buffer to move around
|
||||||
// the history, we make buffer the current line
|
// the history, we make buffer the current line
|
||||||
if rl.histPos == 0 && (rl.histPos+i) == 1 {
|
if rl.histOffset == 0 && rl.histOffset + i == 1 {
|
||||||
rl.lineBuf = string(rl.line)
|
rl.lineBuf = string(rl.line)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch rl.histPos + i {
|
rl.histOffset += i
|
||||||
case 0, history.Len() + 1:
|
if rl.histOffset == 0 {
|
||||||
rl.histPos = 0
|
|
||||||
rl.line = []rune(rl.lineBuf)
|
rl.line = []rune(rl.lineBuf)
|
||||||
rl.pos = len(rl.lineBuf)
|
rl.pos = len(rl.lineBuf)
|
||||||
return
|
} else if rl.histOffset <= -1 {
|
||||||
case -1:
|
rl.histOffset = 0
|
||||||
rl.histPos = 0
|
} else {
|
||||||
rl.lineBuf = string(rl.line)
|
|
||||||
default:
|
|
||||||
dedup = true
|
dedup = true
|
||||||
old = string(rl.line)
|
old = string(rl.line)
|
||||||
new, err = history.GetLine(history.Len() - rl.histPos - 1)
|
new, err = history.GetLine(history.Len() - rl.histOffset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rl.resetHelpers()
|
rl.resetHelpers()
|
||||||
print("\r\n" + err.Error() + "\r\n")
|
print("\r\n" + err.Error() + "\r\n")
|
||||||
|
@ -148,7 +145,6 @@ func (rl *Instance) walkHistory(i int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rl.clearLine()
|
rl.clearLine()
|
||||||
rl.histPos += i
|
|
||||||
rl.line = []rune(new)
|
rl.line = []rune(new)
|
||||||
rl.pos = len(rl.line)
|
rl.pos = len(rl.line)
|
||||||
if rl.pos > 0 {
|
if rl.pos > 0 {
|
||||||
|
|
|
@ -134,6 +134,7 @@ type Instance struct {
|
||||||
// history operating params
|
// history operating params
|
||||||
lineBuf string
|
lineBuf string
|
||||||
histPos int
|
histPos int
|
||||||
|
histOffset int
|
||||||
histNavIdx int // Used for quick history navigation.
|
histNavIdx int // Used for quick history navigation.
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -49,7 +49,7 @@ func (rl *Instance) Readline() (string, error) {
|
||||||
|
|
||||||
// History Init
|
// History Init
|
||||||
// We need this set to the last command, so that we can access it quickly
|
// We need this set to the last command, so that we can access it quickly
|
||||||
rl.histPos = 0
|
rl.histOffset = 0
|
||||||
rl.viUndoHistory = []undoItem{{line: "", pos: 0}}
|
rl.viUndoHistory = []undoItem{{line: "", pos: 0}}
|
||||||
|
|
||||||
// Multisplit
|
// Multisplit
|
||||||
|
@ -546,6 +546,10 @@ func (rl *Instance) Readline() (string, error) {
|
||||||
// entry readline is currently configured for and then update the line entries
|
// entry readline is currently configured for and then update the line entries
|
||||||
// accordingly.
|
// accordingly.
|
||||||
func (rl *Instance) editorInput(r []rune) {
|
func (rl *Instance) editorInput(r []rune) {
|
||||||
|
if len(r) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
switch rl.modeViMode {
|
switch rl.modeViMode {
|
||||||
case VimKeys:
|
case VimKeys:
|
||||||
rl.vi(r[0])
|
rl.vi(r[0])
|
||||||
|
|
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
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
function git_short_hash {
|
||||||
|
short_hash="$(cached git_short_hash)"
|
||||||
|
|
||||||
|
if [ -z "$short_hash" ]; then
|
||||||
|
short_hash="$(git rev-parse --short HEAD)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
output "$short_hash"
|
||||||
|
}
|
||||||
|
|
||||||
|
function git_tag_version {
|
||||||
|
tag="$(cached git_tag_version)"
|
||||||
|
|
||||||
|
if [ -z "$tag" ]; then
|
||||||
|
tag="$(git describe --tags --abbrev=0)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove the potential prefix of `v`
|
||||||
|
if [[ $tag =~ ^v[0-9].* ]]; then
|
||||||
|
tag="${tag:1}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
tag="${tag/"-"/"."}"
|
||||||
|
output "$tag"
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ var (
|
||||||
.. hilbish.userDir.config .. '/hilbish/?/init.lua;'
|
.. hilbish.userDir.config .. '/hilbish/?/init.lua;'
|
||||||
.. hilbish.userDir.config .. '/hilbish/?/?.lua;'
|
.. hilbish.userDir.config .. '/hilbish/?/?.lua;'
|
||||||
.. hilbish.userDir.config .. '/hilbish/?.lua'`
|
.. hilbish.userDir.config .. '/hilbish/?.lua'`
|
||||||
dataDir = "/usr/share/hilbish"
|
dataDir = "/usr/local/share/hilbish"
|
||||||
preloadPath = dataDir + "/nature/init.lua"
|
preloadPath = dataDir + "/nature/init.lua"
|
||||||
sampleConfPath = dataDir + "/.hilbishrc.lua" // Path to default/sample config
|
sampleConfPath = dataDir + "/.hilbishrc.lua" // Path to default/sample config
|
||||||
defaultConfDir = ""
|
defaultConfDir = ""
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
title: "{{ replace .Name "-" " " | title }}"
|
||||||
|
date: {{ .Date }}
|
||||||
|
draft: true
|
||||||
|
---
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
baseURL = 'https://rosettea.github.io/Hilbish/'
|
||||||
|
languageCode = 'en-us'
|
||||||
|
title = 'Hilbish'
|
||||||
|
theme = 'hsh'
|
||||||
|
enableGitInfo = true
|
||||||
|
|
||||||
|
[menu]
|
||||||
|
[[menu.nav]]
|
||||||
|
identifier = 'home'
|
||||||
|
name = 'Home'
|
||||||
|
pageref = '/'
|
||||||
|
weight = 1
|
||||||
|
[[menu.nav]]
|
||||||
|
identifier = 'install'
|
||||||
|
name = 'Install'
|
||||||
|
pageref = '/install'
|
||||||
|
weight = 2
|
||||||
|
[[menu.nav]]
|
||||||
|
identifier = 'docs'
|
||||||
|
name = 'Docs'
|
||||||
|
pageref = '/docs'
|
||||||
|
weight = 3
|
||||||
|
|
||||||
|
[markup.goldmark.renderer]
|
||||||
|
unsafe = true
|
|
@ -0,0 +1,134 @@
|
||||||
|
---
|
||||||
|
description: 'Something Unique. Hilbish is the new interactive shell for Lua fans. Extensible, scriptable, configurable: All in Lua.'
|
||||||
|
---
|
||||||
|
|
||||||
|
[//]: <>
|
||||||
|
|
||||||
|
<!-- hugo (prob goldmark) is funny; the html wont work if its the first thing -->
|
||||||
|
<div class="text-center">
|
||||||
|
<h1 class="fw-light">Something Unique.</h1>
|
||||||
|
<p>
|
||||||
|
<strong>Hilbish</strong> is the new interactive shell for Lua fans.<br>
|
||||||
|
Extensible, scriptable, configurable: All in Lua.
|
||||||
|
</p>
|
||||||
|
<a href="install" class="btn btn-primary">Install</a>
|
||||||
|
<a href="https://github.com/Rosettea/Hilbish" class="btn btn-secondary" target="_blank">Github</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="row row-cols-1 row-cols-md-2 g-4">
|
||||||
|
<div class="col">
|
||||||
|
<div class="card border-light mb-3">
|
||||||
|
<div class="row g-0">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<a href="https://safe.kashima.moe/6njmopm47u1x.png">
|
||||||
|
<img src="https://safe.kashima.moe/6njmopm47u1x.png" class="img-fluid rounded-start">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<h5 class="card-header">Simple and Easy Scripting</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text">
|
||||||
|
Hilbish is configured and scripted in the Lua programming language.
|
||||||
|
This removes all the old, ugly things about Shell script and introduces
|
||||||
|
everything good about Lua, including other languages (Moonscript & Fennel).
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="card border-light mb-3">
|
||||||
|
<div class="row g-0">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<a href="https://safe.kashima.moe/jkndbi636lzj.png">
|
||||||
|
<img src="https://safe.kashima.moe/jkndbi636lzj.png" class="img-fluid rounded-start">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<h5 class="card-header">History and Completion Menus</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text">
|
||||||
|
Hilbish provides the user with proper menus for completions,
|
||||||
|
history searching. Want to see your previous commands? Hit Ctrl-R.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="card border-light mb-3">
|
||||||
|
<div class="row g-0">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<a href="https://safe.kashima.moe/6yfeooamzro4.png">
|
||||||
|
<img src="https://safe.kashima.moe/6yfeooamzro4.png" class="img-fluid rounded-start">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<h5 class="card-header">Tons of Features, and More to Come</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text">
|
||||||
|
Hilbish offers a bunch of features to make your interactive
|
||||||
|
shell experience rich. Things like syntax highlighting and hinting
|
||||||
|
available via the Lua API.
|
||||||
|
</p>
|
||||||
|
<p class="card-small text-muted">* Command hints shown in photo are not default.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- uncomment, replace top when editor interface can be replaced (and replace the images) -->
|
||||||
|
<!--
|
||||||
|
<div class="col">
|
||||||
|
<div class="card border-light mb-3">
|
||||||
|
<div class="row g-0">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<a href="https://safe.kashima.moe/6yfeooamzro4.png">
|
||||||
|
<img src="https://safe.kashima.moe/6yfeooamzro4.png" class="img-fluid rounded-start">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<h5 class="card-header">Highly Extensible</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text">
|
||||||
|
Hilbish can be turned into an all new shell if wanted. One of our
|
||||||
|
main goals is that most (if not all) interfaces can be replaced.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1 class="fw-light">Why not just Lua?</h1>
|
||||||
|
<p>
|
||||||
|
Hilbish is your interactive shell as well as a just a Lua interpreter
|
||||||
|
and enhanced REPL.<br>
|
||||||
|
</p>
|
||||||
|
<ul class="list-group" style="max-width: 64em;">
|
||||||
|
<li class="list-group-item"><i class="fa-solid fa-battery-full"></i> Batteries included Lua runtime that's also your user shell!</li>
|
||||||
|
<li class="list-group-item"><i class="fa-solid fa-network-wired"></i> Hilbish is easily cross platform. It has OS agnostic interfaces for easy cross platform Lua code.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<h1 class="fw-light">Try It Today!</h1>
|
||||||
|
<p>
|
||||||
|
Hilbish is known to run on the 3 major platforms (Windows, MacOS, Linux)
|
||||||
|
but likely builds on other Unixes!
|
||||||
|
<br>
|
||||||
|
Windows doesn't work as well as it should, so if you're a Windows user,
|
||||||
|
<a href="https://github.com/Rosettea/Hilbish/discussions/165">say something</a>!
|
||||||
|
<ul class="list-group" style="max-width: 64em;">
|
||||||
|
<li class="list-group-item"><i class="fa-solid fa-cloud-arrow-down"></i> <a href="/Hilbish/install" style="text-decoration: none;"><strong>Download</strong></a> the binary</li>
|
||||||
|
<li class="list-group-item"><i class="fa-solid fa-screwdriver-wrench"></i> <a href="https://github.com/Rosettea/Hilbish#manual-build" style="text-decoration: none;"><strong>Build</strong></a> from source</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
title: Introduction
|
||||||
|
layout: doc
|
||||||
|
weight: -1
|
||||||
|
menu: docs
|
||||||
|
---
|
||||||
|
|
||||||
|
Here lies the documentation for Hilbish, the hyper extensible Lua shell.
|
||||||
|
Hilbish provides you with a few quality of life features and useful
|
||||||
|
functions to ensure you can make the shell fully yours.
|
||||||
|
|
||||||
|
These features include:
|
||||||
|
- Completion and history search menus
|
||||||
|
- Hinting and syntax highlighting (scripted by user)
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
Steps on installing Hilbish will be at the Install page in the navigation bar
|
||||||
|
at the top. This also included getting development builds from the GitHub
|
||||||
|
repository.
|
|
@ -0,0 +1 @@
|
||||||
|
../../../docs/api/
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
title: Frequently Asked Questions
|
||||||
|
layout: doc
|
||||||
|
weight: -20
|
||||||
|
menu: docs
|
||||||
|
---
|
||||||
|
|
||||||
|
# Is Hilbish POSIX compliant?
|
||||||
|
No, it is not. POSIX compliance is a non-goal. Perhaps in the future,
|
||||||
|
someone would be able to write a native plugin to support shell scripting
|
||||||
|
(which would be against it's main goal, but ....)
|
||||||
|
|
||||||
|
# Windows Support?
|
||||||
|
It compiles for Windows (CI ensures it does), but otherwise it is not
|
||||||
|
directly supported. If you'd like to improve this situation,
|
||||||
|
checkout [the discussion](https://github.com/Rosettea/Hilbish/discussions/165).
|
||||||
|
|
||||||
|
# Where is the API documentation?
|
||||||
|
The builtin `doc` command supplies all documentation of Hilbish provided
|
||||||
|
APIs. This will be on the website in the near future.
|
||||||
|
|
||||||
|
# Why?
|
||||||
|
Hilbish emerged from the desire of a Lua configured shell.
|
||||||
|
It was the initial reason that it was created, but now it's more:
|
||||||
|
to be hyper extensible, simpler and more user friendly.
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
title: Features
|
||||||
|
layout: doc
|
||||||
|
weight: -40
|
||||||
|
menu: docs
|
||||||
|
---
|
||||||
|
|
||||||
|
Hilbish has a wide range of features to enhance the user's experience and
|
||||||
|
is always adding new ones. If there is something missing here or something
|
||||||
|
you would like to see, please [start a discussion](https://github.com/Rosettea/Hilbish/discussions)
|
||||||
|
or comment on any existing ones which match your request.
|
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
title: Runner Mode
|
||||||
|
description: Customize the interactive script/command runner.
|
||||||
|
layout: doc
|
||||||
|
menu:
|
||||||
|
docs:
|
||||||
|
parent: "Features"
|
||||||
|
---
|
||||||
|
|
||||||
|
Hilbish allows you to change how interactive text can be interpreted.
|
||||||
|
This is mainly due to the fact that the default method Hilbish uses
|
||||||
|
is that it runs Lua first and then falls back to shell script.
|
||||||
|
|
||||||
|
In some cases, someone might want to switch to just shell script to avoid
|
||||||
|
it while interactive but still have a Lua config, or go full Lua to use
|
||||||
|
Hilbish as a REPL. This also allows users to add alternative languages,
|
||||||
|
instead of either like Fennel.
|
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
title: Getting Started
|
||||||
|
layout: doc
|
||||||
|
weight: -10
|
||||||
|
menu: docs
|
||||||
|
---
|
||||||
|
|
||||||
|
To start Hilbish, open a terminal. If Hilbish has been installed and is not the
|
||||||
|
default shell, you can simply run `hilbish` to start it. This will launch
|
||||||
|
a normal interactive session.
|
||||||
|
To exit, you can either run the `exit` command or hit Ctrl+D.
|
||||||
|
|
||||||
|
# Setting as Default
|
||||||
|
## Login shell
|
||||||
|
There are a few ways to make Hilbish your default shell. A simple way is
|
||||||
|
to make it your user/login shell.
|
||||||
|
|
||||||
|
{{< warning `It is not recommended to set Hilbish as your login shell. That is expected to be a
|
||||||
|
POSIX compliant shell, which Hilbish is not. At most, there will just be a
|
||||||
|
few variables missing in your environment` >}}
|
||||||
|
|
||||||
|
To do that, simply run `chsh -s /usr/bin/hilbish`.
|
||||||
|
Some distros (namely Fedora) might have `lchsh` instead, which is used like `lchsh <user>`.
|
||||||
|
When prompted, you can put the path for Hilbish.
|
||||||
|
|
||||||
|
## Default with terminal
|
||||||
|
The simpler way is to set the default shell for your terminal. The way of
|
||||||
|
doing this depends on how your terminal settings are configured.
|
||||||
|
|
||||||
|
## Run after login shell
|
||||||
|
Some shells (like zsh) have an rc file, like `.zlogin`, which is ran when the shell session
|
||||||
|
is a login shell. In that file, you can run Hilbish. Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
exec hilbish -S -l
|
||||||
|
```
|
||||||
|
|
||||||
|
This will replace the shell with Hilbish, set $SHELL to Hilbish and launch it as a login shell.
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
Once installation and setup has been done, you can then configure Hilbish.
|
||||||
|
It is configured and scripted via Lua, so the config file is a Lua file.
|
||||||
|
You can use any pure Lua library to do whatever you want.
|
||||||
|
|
||||||
|
Hilbish's sample configuration is usually located in `hilbish.dataDir .. '/.hilbishrc.lua'`.
|
||||||
|
You can print that path via Lua to see what it is: `print(hilbish.dataDir .. '/.hilbishrc.lua')`.
|
||||||
|
As an example, it will usually will result in `/usr/share/hilbish/.hilbishrc.lua` on Linux.
|
||||||
|
|
||||||
|
To edit your user configuration, you can copy that file to `hilbish.userDir.config .. '/hilbish/init.lua'`,
|
||||||
|
which follows XDG on Linux and MacOS, and is located in %APPDATA% on Windows.
|
||||||
|
|
||||||
|
As the directory is usually `~/.config` on Linux, you can run this command to copy it:
|
||||||
|
`cp /usr/share/hilbish/.hilbishrc.lua ~/.config/hilbish/init.lua`
|
||||||
|
|
||||||
|
Now you can get to editing it. Since it's just a Lua file, having basic
|
||||||
|
knowledge of Lua would help. All of Lua's standard libraries and functions
|
||||||
|
from Lua 5.4 are available. Hilbish has some custom and modules that are
|
||||||
|
available. To see them, you can run the `doc` command. This also works as
|
||||||
|
general documentation for other things.
|
|
@ -0,0 +1,55 @@
|
||||||
|
---
|
||||||
|
title: Install
|
||||||
|
description: Steps on how to install Hilbish on all the OSes and distros supported.
|
||||||
|
layout: page
|
||||||
|
---
|
||||||
|
|
||||||
|
## Official Binaries
|
||||||
|
The best way to get Hilbish is to get a build directly from GitHub.
|
||||||
|
At any time, there are 2 versions of Hilbish recommended for download:
|
||||||
|
the latest stable release, and development builds from the master branch.
|
||||||
|
|
||||||
|
You can download both at any time, but note that the development builds may
|
||||||
|
have breaking changes.
|
||||||
|
|
||||||
|
For the latest **stable release**, check here: https://github.com/Rosettea/Hilbish/releases/latest
|
||||||
|
For a **development build**: https://nightly.link/Rosettea/Hilbish/workflows/build/master
|
||||||
|
|
||||||
|
## Package Repositories
|
||||||
|
### Fedora (COPR)
|
||||||
|
An official COPR is offered to install Hilbish easily on Fedora.
|
||||||
|
Enable the repo:
|
||||||
|
```
|
||||||
|
sudo dnf copr enable sammyette/Hilbish
|
||||||
|
```
|
||||||
|
|
||||||
|
And install Hilbish:
|
||||||
|
```
|
||||||
|
sudo dnf install hilbish
|
||||||
|
```
|
||||||
|
|
||||||
|
Or for the latest development build from master:
|
||||||
|
```
|
||||||
|
sudo dnf install hilbish-git
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arch Linux (AUR)
|
||||||
|
Hilbish is on the AUR. Setup an AUR helper, and install.
|
||||||
|
Example with yay:
|
||||||
|
|
||||||
|
```
|
||||||
|
yay -S hilbish
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, from master branch:
|
||||||
|
```
|
||||||
|
yay -S hilbish-git
|
||||||
|
```
|
||||||
|
|
||||||
|
### Alpine Linux
|
||||||
|
Hilbish is currentlty in the testing/edge repository for Alpine.
|
||||||
|
Follow the steps [here](https://wiki.alpinelinux.org/wiki/Enable_Community_Repository)
|
||||||
|
(Using testing repositories) and install:
|
||||||
|
```
|
||||||
|
apk add hilbish
|
||||||
|
```
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Rosettea
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,2 @@
|
||||||
|
+++
|
||||||
|
+++
|
|
@ -0,0 +1,7 @@
|
||||||
|
{{ define "main"}}
|
||||||
|
<main id="main">
|
||||||
|
<div>
|
||||||
|
<h1><a href="{{ "/" | relURL }}">Go Home</a></h1>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<h{{ (add .Level 1) }} id="{{ .Anchor | safeURL }}">
|
||||||
|
{{ .Text | safeHTML }}
|
||||||
|
</h{{ (add .Level 1) }}>
|
||||||
|
{{ if eq .Text ""}}
|
||||||
|
<hr>
|
||||||
|
{{ end }}
|
|
@ -0,0 +1,4 @@
|
||||||
|
<a href="{{ .Destination | safeURL }}"{{ with .Title}} title="{{ . }}"{{ end }}{{ if eq (substr .Destination 0 4) "http" }} target="_blank" rel="noopener"{{ end }}>
|
||||||
|
{{ .Text | safeHTML }}
|
||||||
|
</a>
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
{{- partial "head.html" . -}}
|
||||||
|
<body class="d-flex flex-column min-vh-100" style="overflow-x: hidden;">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||||||
|
<symbol id="check-circle-fill" fill="currentColor" viewBox="0 0 16 16">
|
||||||
|
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="info-fill" fill="currentColor" viewBox="0 0 16 16">
|
||||||
|
<path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm.93-9.412-1 4.705c-.07.34.029.533.304.533.194 0 .487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598-.703 0-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081.082-.381 2.29-.287zM8 5.5a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="exclamation-triangle-fill" fill="currentColor" viewBox="0 0 16 16">
|
||||||
|
<path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{{- partial "header.html" . -}}
|
||||||
|
{{- block "main" . }}{{- end }}
|
||||||
|
{{- partial "footer.html" . -}}
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,53 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<div class="container py-3 row">
|
||||||
|
<div class="container" style="width: 240px;">
|
||||||
|
<div class="p-3 col">
|
||||||
|
<ul class="nav nav-pills mb-auto collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
{{ $currentPage := . }}
|
||||||
|
{{ range .Site.Menus.docs.ByWeight.Reverse }}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ .URL }}" class="nav-link">
|
||||||
|
<strong>{{ .Title }}</strong>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{{ if .Children }}
|
||||||
|
<ul style="list-style: none;">
|
||||||
|
{{ range .Children }}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ .URL }}" class="nav-link">
|
||||||
|
{{ .Title }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-3 col">
|
||||||
|
<div>
|
||||||
|
<h1>{{ .Title }}</h1>
|
||||||
|
<p><em>
|
||||||
|
{{ $date := .Date.UTC.Format "Jan 2, 2006" }}
|
||||||
|
{{ $lastmod := .Lastmod.UTC.Format "Jan 2, 2006" }}
|
||||||
|
{{ if and (ne $lastmod $date) (gt .Lastmod .Date) }}
|
||||||
|
Last updated {{ $lastmod }}<br>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if .Description }}
|
||||||
|
{{ .Description }}<br>
|
||||||
|
{{ end}}
|
||||||
|
</em></p>
|
||||||
|
{{.Content}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer mt-auto">
|
||||||
|
<p class="card-small text-muted">
|
||||||
|
Want to help improve this page? <a href="https://github.com/Rosettea/Hilbish/issues/new/choose">Create an issue.</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main>
|
||||||
|
<div class="container mt-2">
|
||||||
|
{{.Content}}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main>
|
||||||
|
<div class="container mt-2">
|
||||||
|
<h1>{{ .Title }}</h1>
|
||||||
|
{{.Content}}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main style="max-width: 80em; margin: auto;">
|
||||||
|
{{.Content}}
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<footer class="footer mt-auto mt-auto py-3 bg-light row">
|
||||||
|
<div class="col mb-3">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col mb-3">
|
||||||
|
<a href="/Hilbish" class="d-flex align-items-center mb-3 link-dark text-decoration-none">
|
||||||
|
<img src="/Hilbish/hilbish-flower.png" alt="" height="48" class="d-inline-block align-text-top">
|
||||||
|
</a>
|
||||||
|
<p class="text-muted">
|
||||||
|
Rosettea © 2022
|
||||||
|
<br>
|
||||||
|
Made with <i class="fa-solid fa-heart" style="color: #f6345b;"></i>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col mb-3"></div>
|
||||||
|
<div class="col mb-3"></div>
|
||||||
|
<div class="col mb-3"></div>
|
||||||
|
|
||||||
|
<div class="col mb-3">
|
||||||
|
<h5>Hilbish</h5>
|
||||||
|
<ul class="nav flex-column">
|
||||||
|
<li class="nav-item mb-2"><a href="/Hilbish" class="nav-link p-0 text-muted">Home</a></li>
|
||||||
|
<li class="nav-item mb-2"><a href="/Hilbish/docs/faq" class="nav-link p-0 text-muted">FAQ</a></li>
|
||||||
|
<li class="nav-item mb-2"><a href="https://github.com/Rosettea/Hilbish" class="nav-link p-0 text-muted">Source</a></li>
|
||||||
|
<li class="nav-item mb-2"><a href="https://github.com/Rosettea/Hilbish/releases" class="nav-link p-0 text-muted">Releases</a></li>
|
||||||
|
<li class="nav-item mb-2"><a href="/Hilbish/docs" class="nav-link p-0 text-muted">Documentation</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col mb-3"></div>
|
||||||
|
</footer>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<head>
|
||||||
|
{{ $title := print .Title " — " .Site.Title }}
|
||||||
|
{{ if .IsHome }}{{ $title = .Site.Title }}{{ end }}
|
||||||
|
<title>{{ $title }}</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"/>
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#ff89dd">
|
||||||
|
<meta content="/Hilbish/hilbish-flower.png" property="og:image" />
|
||||||
|
|
||||||
|
<meta property="og:site_name" content="Hilbish" />
|
||||||
|
<meta content="{{ $title }}" property="og:title" />
|
||||||
|
<meta content="{{if .Description}}{{ .Description }}{{ else }}{{ .Summary }}{{ end }}" property="og:description" />
|
||||||
|
<meta content="{{if .Description}}{{ .Description }}{{ else }}{{ .Summary }}{{ end }}" name="description" />
|
||||||
|
|
||||||
|
<meta name="revisit-after" content="2 days">
|
||||||
|
<meta name="keywords" content="Lua, Hilbish, Linux, Shell">
|
||||||
|
|
||||||
|
<meta property="og:locale" content="en_GB" />
|
||||||
|
<link rel="canonical" href="https://rosettea.github.io/Hilbish/" />
|
||||||
|
<meta property="og:url" content="https://rosettea.github.io/Hilbish/" />
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
|
</head>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<header>
|
||||||
|
<nav class="navbar navbar-expand-md sticky-top bg-light">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="/Hilbish">
|
||||||
|
<img src="/Hilbish/hilbish-flower.png" alt="" height="24" class="d-inline-block align-text-top">
|
||||||
|
Hilbish
|
||||||
|
</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||||
|
{{ $currentPage := . }}
|
||||||
|
{{ range .Site.Menus.nav }}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ .URL }}" class="nav-link {{ if $currentPage.IsMenuCurrent "nav" . }}active{{ end }}">
|
||||||
|
{{ .Name }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</header>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<div class="alert alert-warning d-flex align-items-center" role="alert">
|
||||||
|
<svg class="bi flex-shrink-0 me-2" width="24" height="24" role="img" aria-label="Warning:"><use xlink:href="#exclamation-triangle-fill"/></svg>
|
||||||
|
<div>
|
||||||
|
{{ .Get 0 }}
|
||||||
|
</div>
|
||||||
|
</div>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue