2
2
mirror of https://github.com/Hilbis/Hilbish synced 2025-07-03 01:32:03 +00:00

Compare commits

...

13 Commits

19 changed files with 777 additions and 450 deletions

34
api.go
View File

@ -38,7 +38,6 @@ var exports = map[string]util.LuaExport{
"complete": {hlcomplete, 2, false}, "complete": {hlcomplete, 2, false},
"cwd": {hlcwd, 0, false}, "cwd": {hlcwd, 0, false},
"exec": {hlexec, 1, false}, "exec": {hlexec, 1, false},
"runnerMode": {hlrunnerMode, 1, false},
"goro": {hlgoro, 1, true}, "goro": {hlgoro, 1, true},
"highlighter": {hlhighlighter, 1, false}, "highlighter": {hlhighlighter, 1, false},
"hinter": {hlhinter, 1, false}, "hinter": {hlhinter, 1, false},
@ -301,7 +300,7 @@ hilbish.multiprompt '-->'
*/ */
func hlmultiprompt(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { func hlmultiprompt(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 c.PushingNext1(t.Runtime, rt.StringValue(multilinePrompt)), nil
} }
prompt, err := c.StringArg(0) prompt, err := c.StringArg(0)
if err != nil { if err != nil {
@ -639,37 +638,6 @@ func hlinputMode(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
return c.Next(), nil return c.Next(), nil
} }
// runnerMode(mode)
// **NOTE: This function is deprecated and will be removed in 3.0**
// Use `hilbish.runner.setCurrent` instead.
// 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.
// Read [about runner mode](../features/runner-mode) for more information.
// #param mode string|function
func hlrunnerMode(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
// TODO: Reimplement in Lua
if err := c.Check1Arg(); err != nil {
return nil, err
}
mode := c.Arg(0)
switch mode.Type() {
case rt.StringType:
switch mode.AsString() {
case "hybrid", "hybridRev", "lua", "sh": runnerMode = mode
default: return nil, errors.New("execMode: expected either a function or hybrid, hybridRev, lua, sh. Received " + mode.AsString())
}
case rt.FunctionType: runnerMode = mode
default: return nil, errors.New("execMode: expected either a function or hybrid, hybridRev, lua, sh. Received " + mode.TypeName())
}
return c.Next(), nil
}
// hinter(line, pos) // hinter(line, pos)
// The command line hint handler. It gets called on every key insert to // 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 // determine what text to use as an inline hint. It is passed the current

View File

@ -84,6 +84,7 @@ var prefix = map[string]string{
"commander": "c", "commander": "c",
"bait": "b", "bait": "b",
"terminal": "term", "terminal": "term",
"snail": "snail",
} }
func getTagsAndDocs(docs string) (map[string][]tag, []string) { func getTagsAndDocs(docs string) (map[string][]tag, []string) {
@ -203,11 +204,16 @@ func setupDocType(mod string, typ *doc.Type) *docPiece {
} }
typeTable[strings.ToLower(typeName)] = []string{parentMod, interfaces} typeTable[strings.ToLower(typeName)] = []string{parentMod, interfaces}
println(typeName, parentMod, interfaces)
return dps return dps
} }
func setupDoc(mod string, fun *doc.Func) *docPiece { func setupDoc(mod string, fun *doc.Func) *docPiece {
if fun.Doc == "" {
return nil
}
docs := strings.TrimSpace(fun.Doc) docs := strings.TrimSpace(fun.Doc)
tags, parts := getTagsAndDocs(docs) tags, parts := getTagsAndDocs(docs)
@ -320,7 +326,7 @@ provided by Hilbish.
os.Mkdir("emmyLuaDocs", 0777) os.Mkdir("emmyLuaDocs", 0777)
dirs := []string{"./"} dirs := []string{"./", "./util"}
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() {
return nil return nil
@ -347,7 +353,7 @@ provided by Hilbish.
pieces := []docPiece{} pieces := []docPiece{}
typePieces := []docPiece{} typePieces := []docPiece{}
mod := l mod := l
if mod == "main" { if mod == "main" || mod == "util" {
mod = "hilbish" mod = "hilbish"
} }
var hasInterfaces bool var hasInterfaces bool
@ -431,14 +437,25 @@ provided by Hilbish.
interfaceModules[modname].Types = append(interfaceModules[modname].Types, piece) interfaceModules[modname].Types = append(interfaceModules[modname].Types, piece)
} }
docs[mod] = module{ println(mod)
Types: filteredTypePieces, fmt.Println(filteredTypePieces)
Docs: filteredPieces, if newDoc, ok := docs[mod]; ok {
ShortDescription: shortDesc, println("fuck")
Description: strings.Join(desc, "\n"), oldMod := docs[mod]
HasInterfaces: hasInterfaces, newDoc.Types = append(filteredTypePieces, oldMod.Types...)
Properties: docPieceTag("property", tags), newDoc.Docs = append(filteredPieces, oldMod.Docs...)
Fields: docPieceTag("field", tags),
docs[mod] = newDoc
} else {
docs[mod] = module{
Types: filteredTypePieces,
Docs: filteredPieces,
ShortDescription: shortDesc,
Description: strings.Join(desc, "\n"),
HasInterfaces: hasInterfaces,
Properties: docPieceTag("property", tags),
Fields: docPieceTag("field", tags),
}
} }
} }

View File

@ -15,7 +15,6 @@ for _, fname in ipairs(files) do
local mod = header:match(modpattern) local mod = header:match(modpattern)
if not mod then goto continue end if not mod then goto continue end
print(fname, mod)
pieces[mod] = {} pieces[mod] = {}
descriptions[mod] = {} descriptions[mod] = {}
@ -42,10 +41,12 @@ for _, fname in ipairs(files) do
local dps = { local dps = {
description = {}, description = {},
example = {},
params = {} params = {}
} }
local offset = 1 local offset = 1
local doingExample = false
while true do while true do
local prev = lines[lineno - offset] local prev = lines[lineno - offset]
@ -59,17 +60,25 @@ for _, fname in ipairs(files) do
if emmy then if emmy then
if emmy == 'param' then if emmy == 'param' then
print('bruh', emmythings[1], emmythings[2])
table.insert(dps.params, 1, { table.insert(dps.params, 1, {
name = emmythings[1], name = emmythings[1],
type = emmythings[2], type = emmythings[2],
-- the +1 accounts for space. -- the +1 accounts for space.
description = table.concat(emmythings, ' '):sub(emmythings[1]:len() + 1 + emmythings[2]:len() + 1) description = table.concat(emmythings, ' '):sub(emmythings[1]:len() + 1 + emmythings[2]:len() + 1)
}) })
print(table.concat(emmythings, '/'))
end end
else else
table.insert(dps.description, 1, docline) if docline:match '#example' then
doingExample = not doingExample
end
if not docline:match '#example' then
if doingExample then
table.insert(dps.example, 1, docline)
else
table.insert(dps.description, 1, docline)
end
end
end end
offset = offset + 1 offset = offset + 1
else else
@ -77,7 +86,7 @@ for _, fname in ipairs(files) do
end end
end end
pieces[mod][funcName] = dps table.insert(pieces[mod], {funcName, dps})
end end
docPiece = {} docPiece = {}
goto continue2 goto continue2
@ -109,11 +118,15 @@ for iface, dps in pairs(pieces) do
docParent = "API" docParent = "API"
path = string.format('docs/api/%s/%s.md', mod, iface) path = string.format('docs/api/%s/%s.md', mod, iface)
end end
if iface == 'hilbish' then
docParent = "API"
path = string.format('docs/api/hilbish/_index.md', mod, iface)
end
fs.mkdir(fs.dir(path), true) fs.mkdir(fs.dir(path), true)
local exists = pcall(fs.stat, path) local exists = pcall(fs.stat, path)
local newOrNotNature = exists and mod ~= 'nature' local newOrNotNature = (exists and mod ~= 'nature') or iface == 'hilbish'
local f <close> = io.open(path, newOrNotNature and 'r+' or 'w+') local f <close> = io.open(path, newOrNotNature and 'r+' or 'w+')
local tocPos local tocPos
@ -129,9 +142,6 @@ for iface, dps in pairs(pieces) do
tocPos = f:seek() tocPos = f:seek()
end end
end end
print(f)
print('mod and path:', mod, path)
local tocSearch = false local tocSearch = false
for line in f:lines() do for line in f:lines() do
@ -144,7 +154,10 @@ for iface, dps in pairs(pieces) do
end end
end end
for func, docs in pairs(dps) do table.sort(dps, function(a, b) return a[1] < b[1] end)
for _, piece in pairs(dps) do
local func = piece[1]
local docs = piece[2]
local sig = string.format('%s.%s(', iface, func) local sig = string.format('%s.%s(', iface, func)
local params = '' local params = ''
for idx, param in ipairs(docs.params) do for idx, param in ipairs(docs.params) do
@ -186,6 +199,10 @@ for iface, dps in pairs(pieces) do
f:write(string.format('`%s` **`%s`** \n', param.name:gsub('%?$', ''), param.type)) f:write(string.format('`%s` **`%s`** \n', param.name:gsub('%?$', ''), param.type))
f:write(string.format('%s\n\n', param.description)) f:write(string.format('%s\n\n', param.description))
end end
if #docs.example ~= 0 then
f:write '#### Example\n'
f:write(string.format('```lua\n%s\n```\n', table.concat(docs.example, '\n')))
end
--[[ --[[
local params = table.filter(docs, function(t) local params = table.filter(docs, function(t)
return t:match '^%-%-%- @param' return t:match '^%-%-%- @param'

View File

@ -28,10 +28,10 @@ interfaces and functions which directly relate to shell functionality.
|<a href="#prependPath">prependPath(dir)</a>|Prepends `dir` to $PATH.| |<a href="#prependPath">prependPath(dir)</a>|Prepends `dir` to $PATH.|
|<a href="#prompt">prompt(str, typ)</a>|Changes the shell prompt to the provided string.| |<a href="#prompt">prompt(str, typ)</a>|Changes the shell prompt to the provided string.|
|<a href="#read">read(prompt) -> input (string)</a>|Read input from the user, using Hilbish's line editor/input reader.| |<a href="#read">read(prompt) -> input (string)</a>|Read input from the user, using Hilbish's line editor/input reader.|
|<a href="#run">run(cmd, streams) -> exitCode (number), stdout (string), stderr (string)</a>|Runs `cmd` in Hilbish's shell script interpreter.|
|<a href="#runnerMode">runnerMode(mode)</a>|Sets the execution/runner mode for interactive Hilbish.|
|<a href="#timeout">timeout(cb, time) -> @Timer</a>|Executed the `cb` function after a period of `time`.| |<a href="#timeout">timeout(cb, time) -> @Timer</a>|Executed the `cb` function after a period of `time`.|
|<a href="#which">which(name) -> string</a>|Checks if `name` is a valid command.| |<a href="#which">which(name) -> string</a>|Checks if `name` is a valid command.|
|<a href="#runnerMode">runnerMode(mode)</a>|Sets the execution/runner mode for interactive Hilbish.|
|<a href="#run">run(cmd, streams)</a>|Runs `cmd` in Hilbish's shell script interpreter.|
## Static module fields ## Static module fields
||| |||
@ -408,72 +408,6 @@ Returns `input`, will be nil if Ctrl-D is pressed, or an error occurs.
`string` **`prompt?`** `string` **`prompt?`**
Text to print before input, can be empty. Text to print before input, can be empty.
</div>
<hr>
<div id='run'>
<h4 class='heading'>
hilbish.run(cmd, streams) -> exitCode (number), stdout (string), stderr (string)
<a href="#run" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Runs `cmd` in Hilbish's shell script interpreter.
The `streams` parameter specifies the output and input streams the command should use.
For example, to write command output to a sink.
As a table, the caller can directly specify the standard output, error, and input
streams of the command with the table keys `out`, `err`, and `input` respectively.
As a boolean, it specifies whether the command should use standard output or return its output streams.
#### Parameters
`string` **`cmd`**
`table|boolean` **`streams`**
#### Example
```lua
// This code is the same as `ls -l | wc -l`
local fs = require 'fs'
local pr, pw = fs.pipe()
hilbish.run('ls -l', {
stdout = pw,
stderr = pw,
})
pw:close()
hilbish.run('wc -l', {
stdin = pr
})
```
</div>
<hr>
<div id='runnerMode'>
<h4 class='heading'>
hilbish.runnerMode(mode)
<a href="#runnerMode" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
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.
Read [about runner mode](../features/runner-mode) for more information.
#### Parameters
`string|function` **`mode`**
</div> </div>
<hr> <hr>
@ -519,8 +453,7 @@ Will return the path of the binary, or a basename if it's a commander.
<hr> <hr>
## Sink ## Sink
A sink is a structure that has input and/or output to/from A sink is a structure that has input and/or output to/from a desination.
a desination.
### Methods ### Methods
#### autoFlush(auto) #### autoFlush(auto)
@ -542,3 +475,65 @@ Writes data to a sink.
#### writeln(str) #### writeln(str)
Writes data to a sink with a newline at the end. Writes data to a sink with a newline at the end.
<hr>
<div id='run'>
<h4 class='heading'>
hilbish.run(cmd, streams)
<a href="#run" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Runs `cmd` in Hilbish's shell script interpreter.
The `streams` parameter specifies the output and input streams the command should use.
For example, to write command output to a sink.
As a table, the caller can directly specify the standard output, error, and input
streams of the command with the table keys `out`, `err`, and `input` respectively.
As a boolean, it specifies whether the command should use standard output or return its output streams.
#### Parameters
`cmd` **`string`**
`streams` **`table|boolean`**
#### Example
```lua
-- This code is the same as `ls -l | wc -l`
local fs = require 'fs'
local pr, pw = fs.pipe()
hilbish.run('ls -l', {
stdout = pw,
stderr = pw,
})
pw:close()
hilbish.run('wc -l', {
stdin = pr
})
```
</div>
<hr>
<div id='runnerMode'>
<h4 class='heading'>
hilbish.runnerMode(mode)
<a href="#runnerMode" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Sets the execution/runner mode for interactive Hilbish.
**NOTE: This function is deprecated and will be removed in 3.0**
Use `hilbish.runner.setCurrent` instead.
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.
Read [about runner mode](../features/runner-mode) for more information.
#### Parameters
`mode` **`string|function`**
</div>

View File

@ -0,0 +1,135 @@
---
title: Module hilbish.messages
description: simplistic message passing
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The messages interface defines a way for Hilbish-integrated commands,
user config and other tasks to send notifications to alert the user.z
The `hilbish.message` type is a table with the following keys:
`title` (string): A title for the message notification.
`text` (string): The contents of the message.
`channel` (string): States the origin of the message, `hilbish.*` is reserved for Hilbish tasks.
`summary` (string): A short summary of the `text`.
`icon` (string): Unicode (preferably standard emoji) icon for the message notification
`read` (boolean): Whether the full message has been read or not.
## Functions
|||
|----|----|
|<a href="#unreadCount">unreadCount()</a>|Returns the amount of unread messages.|
|<a href="#send">send(message)</a>|Sends a message.|
|<a href="#readAll">readAll()</a>|Marks all messages as read.|
|<a href="#read">read(idx)</a>|Marks a message at `idx` as read.|
|<a href="#delete">delete(idx)</a>|Deletes the message at `idx`.|
|<a href="#clear">clear()</a>|Deletes all messages.|
|<a href="#all">all()</a>|Returns all messages.|
<hr>
<div id='all'>
<h4 class='heading'>
hilbish.messages.all()
<a href="#all" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns all messages.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='clear'>
<h4 class='heading'>
hilbish.messages.clear()
<a href="#clear" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Deletes all messages.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='delete'>
<h4 class='heading'>
hilbish.messages.delete(idx)
<a href="#delete" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Deletes the message at `idx`.
#### Parameters
`idx` **`number`**
</div>
<hr>
<div id='read'>
<h4 class='heading'>
hilbish.messages.read(idx)
<a href="#read" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Marks a message at `idx` as read.
#### Parameters
`idx` **`number`**
</div>
<hr>
<div id='readAll'>
<h4 class='heading'>
hilbish.messages.readAll()
<a href="#readAll" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Marks all messages as read.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='send'>
<h4 class='heading'>
hilbish.messages.send(message)
<a href="#send" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Sends a message.
#### Parameters
`message` **`hilbish.message`**
</div>
<hr>
<div id='unreadCount'>
<h4 class='heading'>
hilbish.messages.unreadCount()
<a href="#unreadCount" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns the amount of unread messages.
#### Parameters
This function has no parameters.
</div>

View File

@ -54,29 +54,16 @@ end)
## Functions ## Functions
||| |||
|----|----| |----|----|
|<a href="#runner.setMode">setMode(cb)</a>|This is the same as the `hilbish.runnerMode` function.|
|<a href="#runner.lua">lua(cmd)</a>|Evaluates `cmd` as Lua input. This is the same as using `dofile`| |<a href="#runner.lua">lua(cmd)</a>|Evaluates `cmd` as Lua input. This is the same as using `dofile`|
|<a href="#runner.sh">sh(cmd)</a>|Runs a command in Hilbish's shell script interpreter.| |<a href="#sh">sh()</a>|nil|
|<a href="#setMode">setMode(mode)</a>|**NOTE: This function is deprecated and will be removed in 3.0**|
<hr> |<a href="#setCurrent">setCurrent(name)</a>|Sets Hilbish's runner mode by name.|
<div id='runner.setMode'> |<a href="#set">set(name, runner)</a>|*Sets* a runner by name. The difference between this function and|
<h4 class='heading'> |<a href="#run">run(input, priv)</a>|Runs `input` with the currently set Hilbish runner.|
hilbish.runner.setMode(cb) |<a href="#getCurrent">getCurrent()</a>|Returns the current runner by name.|
<a href="#runner.setMode" class='heading-link'> |<a href="#get">get(name)</a>|Get a runner by name.|
<i class="fas fa-paperclip"></i> |<a href="#exec">exec(cmd, runnerName)</a>|Executes `cmd` with a runner.|
</a> |<a href="#add">add(name, runner)</a>|Adds a runner to the table of available runners.|
</h4>
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.
#### Parameters
`function` **`cb`**
</div>
<hr> <hr>
<div id='runner.lua'> <div id='runner.lua'>
@ -97,20 +84,164 @@ or `load`, but is appropriated for the runner interface.
</div> </div>
<hr> <hr>
<div id='runner.sh'> <div id='add'>
<h4 class='heading'> <h4 class='heading'>
hilbish.runner.sh(cmd) hilbish.runner.add(name, runner)
<a href="#runner.sh" class='heading-link'> <a href="#add" class='heading-link'>
<i class="fas fa-paperclip"></i> <i class="fas fa-paperclip"></i>
</a> </a>
</h4> </h4>
Runs a command in Hilbish's shell script interpreter. Adds a runner to the table of available runners.
This is the equivalent of using `source`. If runner is a table, it must have the run function in it.
#### Parameters #### Parameters
`string` **`cmd`** `name` **`string`**
Name of the runner
`runner` **`function|table`**
</div> </div>
<hr>
<div id='exec'>
<h4 class='heading'>
hilbish.runner.exec(cmd, runnerName)
<a href="#exec" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Executes `cmd` with a runner.
If `runnerName` is not specified, it uses the default Hilbish runner.
#### Parameters
`cmd` **`string`**
`runnerName` **`string?`**
</div>
<hr>
<div id='get'>
<h4 class='heading'>
hilbish.runner.get(name)
<a href="#get" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Get a runner by name.
#### Parameters
`name` **`string`**
Name of the runner to retrieve.
</div>
<hr>
<div id='getCurrent'>
<h4 class='heading'>
hilbish.runner.getCurrent()
<a href="#getCurrent" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Returns the current runner by name.
#### Parameters
This function has no parameters.
</div>
<hr>
<div id='run'>
<h4 class='heading'>
hilbish.runner.run(input, priv)
<a href="#run" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Runs `input` with the currently set Hilbish runner.
This method is how Hilbish executes commands.
`priv` is an optional boolean used to state if the input should be saved to history.
#### Parameters
`input` **`string`**
`priv` **`bool`**
</div>
<hr>
<div id='set'>
<h4 class='heading'>
hilbish.runner.set(name, runner)
<a href="#set" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
*Sets* a runner by name. The difference between this function and
add, is set will *not* check if the named runner exists.
The runner table must have the run function in it.
#### Parameters
`name` **`string`**
`runner` **`table`**
</div>
<hr>
<div id='setCurrent'>
<h4 class='heading'>
hilbish.runner.setCurrent(name)
<a href="#setCurrent" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Sets Hilbish's runner mode by name.
#### Parameters
`name` **`string`**
</div>
<hr>
<div id='setMode'>
<h4 class='heading'>
hilbish.runner.setMode(mode)
<a href="#setMode" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
**NOTE: This function is deprecated and will be removed in 3.0**
Use `hilbish.runner.setCurrent` instead.
This is the same as the `hilbish.runnerMode` function.
It takes a callback, which will be used to execute all interactive input.
Or a string which names the runner mode to use.
#### Parameters
`mode` **`string|function`**
</div>
<hr>
<div id='sh'>
<h4 class='heading'>
hilbish.runner.sh()
<a href="#sh" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
#### Parameters
This function has no parameters.
</div>

45
docs/api/snail.md Normal file
View File

@ -0,0 +1,45 @@
---
title: Module snail
description: shell script interpreter library
layout: doc
menu:
docs:
parent: "API"
---
## Introduction
The snail library houses Hilbish's Lua wrapper of its shell script interpreter.
It's not very useful other than running shell scripts, which can be done with other
Hilbish functions.
## Functions
|||
|----|----|
|<a href="#new">new() -> @Snail</a>|Creates a new Snail instance.|
<hr>
<div id='new'>
<h4 class='heading'>
snail.new() -> <a href="/Hilbish/docs/api/snail/#snail" style="text-decoration: none;" id="lol">Snail</a>
<a href="#new" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Creates a new Snail instance.
#### Parameters
This function has no parameters.
</div>
## Types
<hr>
## Snail
A Snail is a shell script interpreter instance.
### Methods
#### run(command, streams)
Runs a shell command. Works the same as `hilbish.run`.

View File

@ -15,43 +15,11 @@ directories.
## Functions ## Functions
||| |||
|----|----| |----|----|
|<a href="#setOld">setOld(d)</a>|Sets the old directory string.|
|<a href="#recent">recent(idx)</a>|Get entry from recent directories list based on index.| |<a href="#recent">recent(idx)</a>|Get entry from recent directories list based on index.|
|<a href="#push">push(dir)</a>|Add `dir` to the recent directories list.|
|<a href="#pop">pop(num)</a>|Remove the specified amount of dirs from the recent directories list.| |<a href="#pop">pop(num)</a>|Remove the specified amount of dirs from the recent directories list.|
|<a href="#peak">peak(num)</a>|Look at `num` amount of recent directories, starting from the latest.| |<a href="#peak">peak(num)</a>|Look at `num` amount of recent directories, starting from the latest.|
|<a href="#push">push(dir)</a>|Add `dir` to the recent directories list.|
|<a href="#setOld">setOld(d)</a>|Sets the old directory string.|
<hr>
<div id='setOld'>
<h4 class='heading'>
dirs.setOld(d)
<a href="#setOld" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Sets the old directory string.
#### Parameters
`d` **`string`**
</div>
<hr>
<div id='push'>
<h4 class='heading'>
dirs.push(dir)
<a href="#push" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Add `dir` to the recent directories list.
#### Parameters
`dir` **`string`**
</div>
<hr> <hr>
<div id='peak'> <div id='peak'>
<h4 class='heading'> <h4 class='heading'>
@ -83,6 +51,22 @@ Remove the specified amount of dirs from the recent directories list.
`num` **`number`** `num` **`number`**
</div>
<hr>
<div id='push'>
<h4 class='heading'>
dirs.push(dir)
<a href="#push" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Add `dir` to the recent directories list.
#### Parameters
`dir` **`string`**
</div> </div>
<hr> <hr>
@ -101,3 +85,19 @@ Get entry from recent directories list based on index.
</div> </div>
<hr>
<div id='setOld'>
<h4 class='heading'>
dirs.setOld(d)
<a href="#setOld" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Sets the old directory string.
#### Parameters
`d` **`string`**
</div>

View File

@ -17,29 +17,9 @@ is by the Greenhouse pager.
## Functions ## Functions
||| |||
|----|----| |----|----|
|<a href="#renderInfoBlock">renderInfoBlock(type, text)</a>|Renders an info block. An info block is a block of text with|
|<a href="#renderCodeBlock">renderCodeBlock(text)</a>|Assembles and renders a code block. This returns| |<a href="#renderCodeBlock">renderCodeBlock(text)</a>|Assembles and renders a code block. This returns|
|<a href="#highlight">highlight(text)</a>|Performs basic Lua code highlighting.| |<a href="#highlight">highlight(text)</a>|Performs basic Lua code highlighting.|
|<a href="#renderInfoBlock">renderInfoBlock(type, text)</a>|Renders an info block. An info block is a block of text with|
<hr>
<div id='renderInfoBlock'>
<h4 class='heading'>
doc.renderInfoBlock(type, text)
<a href="#renderInfoBlock" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Renders an info block. An info block is a block of text with
an icon and styled text block.
#### Parameters
`type` **`string`**
Type of info block. The only one specially styled is the `warning`.
`text` **`string`**
</div>
<hr> <hr>
<div id='highlight'> <div id='highlight'>
<h4 class='heading'> <h4 class='heading'>
@ -74,3 +54,23 @@ and styles it to resemble a code block.
</div> </div>
<hr>
<div id='renderInfoBlock'>
<h4 class='heading'>
doc.renderInfoBlock(type, text)
<a href="#renderInfoBlock" class='heading-link'>
<i class="fas fa-paperclip"></i>
</a>
</h4>
Renders an info block. An info block is a block of text with
an icon and styled text block.
#### Parameters
`type` **`string`**
Type of info block. The only one specially styled is the `warning`.
`text` **`string`**
</div>

View File

@ -7,12 +7,6 @@ local hilbish = {}
--- @param cmd string --- @param cmd string
function hilbish.aliases.add(alias, cmd) end 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
--- Returns the current input line. --- Returns the current input line.
function hilbish.editor.getLine() end function hilbish.editor.getLine() end
@ -131,24 +125,6 @@ function hilbish.prompt(str, typ) end
--- Returns `input`, will be nil if Ctrl-D is pressed, or an error occurs. --- Returns `input`, will be nil if Ctrl-D is pressed, or an error occurs.
function hilbish.read(prompt) end function hilbish.read(prompt) end
--- Runs `cmd` in Hilbish's shell script interpreter.
--- The `streams` parameter specifies the output and input streams the command should use.
--- For example, to write command output to a sink.
--- As a table, the caller can directly specify the standard output, error, and input
--- streams of the command with the table keys `out`, `err`, and `input` respectively.
--- As a boolean, it specifies whether the command should use standard output or return its output streams.
---
function hilbish.run(cmd, streams) end
--- 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.
--- Read [about runner mode](../features/runner-mode) for more information.
function hilbish.runnerMode(mode) end
--- Executed the `cb` function after a period of `time`. --- Executed the `cb` function after a period of `time`.
--- This creates a Timer that starts ticking immediately. --- This creates a Timer that starts ticking immediately.
function hilbish.timeout(cb, time) end function hilbish.timeout(cb, time) end
@ -168,28 +144,6 @@ function hilbish.jobs:foreground() end
--- or `load`, but is appropriated for the runner interface. --- or `load`, but is appropriated for the runner interface.
function hilbish.runner.lua(cmd) end function hilbish.runner.lua(cmd) end
--- Sets/toggles the option of automatically flushing output.
--- A call with no argument will toggle the value.
--- @param auto boolean|nil
function hilbish:autoFlush(auto) end
--- Flush writes all buffered input to the sink.
function hilbish:flush() end
--- Reads a liine of input from the sink.
--- @returns string
function hilbish:read() end
--- Reads all input from the sink.
--- @returns string
function hilbish:readAll() end
--- Writes data to a sink.
function hilbish:write(str) end
--- Writes data to a sink with a newline at the end.
function hilbish:writeln(str) end
--- Starts running the job. --- Starts running the job.
function hilbish.jobs:start() end function hilbish.jobs:start() end
@ -200,10 +154,6 @@ function hilbish.jobs:stop() end
--- It will throw if any error occurs. --- It will throw if any error occurs.
function hilbish.module.load(path) end function hilbish.module.load(path) 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. --- Starts a timer.
function hilbish.timers:start() end function hilbish.timers:start() end
@ -262,4 +212,26 @@ function hilbish.timers.create(type, time, callback) end
--- Retrieves a timer via its ID. --- Retrieves a timer via its ID.
function hilbish.timers.get(id) end function hilbish.timers.get(id) end
--- Sets/toggles the option of automatically flushing output.
--- A call with no argument will toggle the value.
--- @param auto boolean|nil
function hilbish:autoFlush(auto) end
--- Flush writes all buffered input to the sink.
function hilbish:flush() end
--- Reads a liine of input from the sink.
--- @returns string
function hilbish:read() end
--- Reads all input from the sink.
--- @returns string
function hilbish:readAll() end
--- Writes data to a sink.
function hilbish:write(str) end
--- Writes data to a sink with a newline at the end.
function hilbish:writeln(str) end
return hilbish return hilbish

11
emmyLuaDocs/snail.lua Normal file
View File

@ -0,0 +1,11 @@
--- @meta
local snail = {}
--- Creates a new Snail instance.
function snail.new() end
--- Runs a shell command. Works the same as `hilbish.run`.
function snail:run(command, streams) end
return snail

83
emmyLuaDocs/util.lua Normal file
View File

@ -0,0 +1,83 @@
--- @meta
local util = {}
---
function util.AbbrevHome changes the user's home directory in the path string to ~ (tilde) end
---
function util. end
---
function util.DoFile runs the contents of the file in the Lua runtime. end
---
function util.DoString runs the code string in the Lua runtime. end
--- directory.
function util.ExpandHome expands ~ (tilde) in the path, changing it to the user home end
---
function util. end
---
function util.ForEach loops through a Lua table. end
---
function util. end
--- a string and a closure.
function util.HandleStrCallback handles function parameters for Go functions which take end
---
function util. end
---
function util. end
---
function util.SetExports puts the Lua function exports in the table. end
--- It is accessible via the __docProp metatable. It is a table of the names of the fields.
function util.SetField sets a field in a table, adding docs for it. end
--- is one which has a metatable proxy to ensure no overrides happen to it.
--- It sets the field in the table and sets the __docProp metatable on the
--- user facing table.
function util.SetFieldProtected sets a field in a protected table. A protected table end
--- Sets/toggles the option of automatically flushing output.
--- A call with no argument will toggle the value.
--- @param auto boolean|nil
function util:autoFlush(auto) end
--- Flush writes all buffered input to the sink.
function util:flush() end
---
function util. end
--- Reads a liine of input from the sink.
--- @returns string
function util:read() end
--- Reads all input from the sink.
--- @returns string
function util:readAll() end
--- Writes data to a sink.
function util:write(str) end
--- Writes data to a sink with a newline at the end.
function util:writeln(str) end
---
function util. end
---
function util. end
---
function util. end
return util

133
exec.go
View File

@ -3,13 +3,9 @@ package main
import ( import (
"errors" "errors"
"fmt" "fmt"
"io"
"os" "os"
"strings" "strings"
"hilbish/util"
//herror "hilbish/errors"
rt "github.com/arnodel/golua/runtime" rt "github.com/arnodel/golua/runtime"
//"github.com/yuin/gopher-lua/parse" //"github.com/yuin/gopher-lua/parse"
) )
@ -20,100 +16,11 @@ var runnerMode rt.Value = rt.NilValue
func runInput(input string, priv bool) { func runInput(input string, priv bool) {
running = true running = true
cmdString := aliases.Resolve(input) runnerRun := hshMod.Get(rt.StringValue("runner")).AsTable().Get(rt.StringValue("run"))
hooks.Emit("command.preexec", input, cmdString) _, err := rt.Call1(l.MainThread(), runnerRun, rt.StringValue(input), rt.BoolValue(priv))
currentRunner := runnerMode
rerun:
var exitCode uint8
var cont bool
var newline bool
// save incase it changes while prompting (For some reason)
input, exitCode, cont, newline, runnerErr, err := runLuaRunner(currentRunner, input)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
cmdFinish(124, input, priv)
return
} }
// we only use `err` to check for lua eval error
// our actual error should only be a runner provided error at this point
// command not found type, etc
err = runnerErr
if cont {
input, err = continuePrompt(input, newline)
if err == nil {
goto rerun
} else if err == io.EOF {
lr.SetPrompt(fmtPrompt(prompt))
}
}
if err != nil && err != io.EOF {
if exErr, ok := util.IsExecError(err); ok {
hooks.Emit("command." + exErr.Typ, exErr.Cmd)
} else {
fmt.Fprintln(os.Stderr, err)
}
}
cmdFinish(exitCode, input, priv)
}
func reprompt(input string, newline bool) (string, error) {
for {
/*
if strings.HasSuffix(input, "\\") {
input = strings.TrimSuffix(input, "\\") + "\n"
}
*/
in, err := continuePrompt(input, newline)
if err != nil {
lr.SetPrompt(fmtPrompt(prompt))
return input, err
}
return in, nil
}
}
func runLuaRunner(runr rt.Value, userInput string) (input string, exitCode uint8, continued bool, newline bool, runnerErr, err error) {
term := rt.NewTerminationWith(l.MainThread().CurrentCont(), 3, false)
err = rt.Call(l.MainThread(), runr, []rt.Value{rt.StringValue(userInput)}, term)
if err != nil {
return "", 124, false, false, nil, err
}
var runner *rt.Table
var ok bool
runnerRet := term.Get(0)
if runner, ok = runnerRet.TryTable(); !ok {
fmt.Fprintln(os.Stderr, "runner did not return a table")
exitCode = 125
input = userInput
return
}
if code, ok := runner.Get(rt.StringValue("exitCode")).TryInt(); ok {
exitCode = uint8(code)
}
if inp, ok := runner.Get(rt.StringValue("input")).TryString(); ok {
input = inp
}
if errStr, ok := runner.Get(rt.StringValue("err")).TryString(); ok {
runnerErr = fmt.Errorf("%s", errStr)
}
if c, ok := runner.Get(rt.StringValue("continue")).TryBool(); ok {
continued = c
}
if nl, ok := runner.Get(rt.StringValue("newline")).TryBool(); ok {
newline = nl
}
return
} }
func handleLua(input string) (string, uint8, error) { func handleLua(input string) (string, uint8, error) {
@ -143,34 +50,6 @@ func handleLua(input string) (string, uint8, error) {
return cmdString, 125, err return cmdString, 125, err
} }
/*
func execSh(cmdString string) (input string, exitcode uint8, cont bool, newline bool, e error) {
_, _, err := execCommand(cmdString, nil)
if err != nil {
// If input is incomplete, start multiline prompting
if syntax.IsIncomplete(err) {
if !interactive {
return cmdString, 126, false, false, err
}
newline := false
if strings.Contains(err.Error(), "unclosed here-document") {
newline = true
}
return cmdString, 126, true, newline, err
} else {
if code, ok := interp.IsExitStatus(err); ok {
return cmdString, code, false, false, nil
} else {
return cmdString, 126, false, false, err
}
}
}
return cmdString, 0, false, false, nil
}
*/
func splitInput(input string) ([]string, string) { func splitInput(input string) ([]string, string) {
// end my suffering // end my suffering
// TODO: refactor this garbage // TODO: refactor this garbage
@ -204,11 +83,3 @@ func splitInput(input string) ([]string, string) {
return cmdArgs, cmdstr.String() return cmdArgs, cmdstr.String()
} }
func cmdFinish(code uint8, cmdstr string, private bool) {
util.SetField(l, hshMod, "exitCode", rt.IntValue(int64(code)))
// using AsValue (to convert to lua type) on an interface which is an int
// results in it being unknown in lua .... ????
// so we allow the hook handler to take lua runtime Values
hooks.Emit("command.exit", rt.IntValue(int64(code)), cmdstr, private)
}

View File

@ -1,3 +1,9 @@
// shell script interpreter library
/*
The snail library houses Hilbish's Lua wrapper of its shell script interpreter.
It's not very useful other than running shell scripts, which can be done with other
Hilbish functions.
*/
package snail package snail
import ( import (
@ -25,7 +31,7 @@ func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
snailMeta := rt.NewTable() snailMeta := rt.NewTable()
snailMethods := rt.NewTable() snailMethods := rt.NewTable()
snailFuncs := map[string]util.LuaExport{ snailFuncs := map[string]util.LuaExport{
"run": {srun, 3, false}, "run": {snailrun, 3, false},
} }
util.SetExports(rtm, snailMethods, snailFuncs) util.SetExports(rtm, snailMethods, snailFuncs)
@ -39,7 +45,7 @@ func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
rtm.SetRegistry(snailMetaKey, rt.TableValue(snailMeta)) rtm.SetRegistry(snailMetaKey, rt.TableValue(snailMeta))
exports := map[string]util.LuaExport{ exports := map[string]util.LuaExport{
"new": util.LuaExport{snew, 0, false}, "new": util.LuaExport{snailnew, 0, false},
} }
mod := rt.NewTable() mod := rt.NewTable()
@ -48,12 +54,17 @@ func loaderFunc(rtm *rt.Runtime) (rt.Value, func()) {
return rt.TableValue(mod), nil return rt.TableValue(mod), nil
} }
func snew(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { // new() -> @Snail
// Creates a new Snail instance.
func snailnew(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
s := New(t.Runtime) s := New(t.Runtime)
return c.PushingNext1(t.Runtime, rt.UserDataValue(snailUserData(s))), nil return c.PushingNext1(t.Runtime, rt.UserDataValue(snailUserData(s))), nil
} }
func srun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { // #member
// run(command, streams)
// Runs a shell command. Works the same as `hilbish.run`.
func snailrun(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.CheckNArgs(2); err != nil { if err := c.CheckNArgs(2); err != nil {
return nil, err return nil, err
} }
@ -157,7 +168,7 @@ func handleStream(v rt.Value, strms *util.Streams, errStream, inStream bool) err
return nil return nil
} }
func snailArg(c *rt.GoCont, arg int) (*snail, error) { func snailArg(c *rt.GoCont, arg int) (*Snail, error) {
s, ok := valueToSnail(c.Arg(arg)) s, ok := valueToSnail(c.Arg(arg))
if !ok { if !ok {
return nil, fmt.Errorf("#%d must be a snail", arg + 1) return nil, fmt.Errorf("#%d must be a snail", arg + 1)
@ -166,17 +177,17 @@ func snailArg(c *rt.GoCont, arg int) (*snail, error) {
return s, nil return s, nil
} }
func valueToSnail(val rt.Value) (*snail, bool) { func valueToSnail(val rt.Value) (*Snail, bool) {
u, ok := val.TryUserData() u, ok := val.TryUserData()
if !ok { if !ok {
return nil, false return nil, false
} }
s, ok := u.Value().(*snail) s, ok := u.Value().(*Snail)
return s, ok return s, ok
} }
func snailUserData(s *snail) *rt.UserData { func snailUserData(s *Snail) *rt.UserData {
snailMeta := s.runtime.Registry(snailMetaKey) snailMeta := s.runtime.Registry(snailMetaKey)
return rt.NewUserData(s, snailMeta.AsTable()) return rt.NewUserData(s, snailMeta.AsTable())
} }

View File

@ -1,4 +1,3 @@
// shell script interpreter library
package snail package snail
import ( import (
@ -23,21 +22,23 @@ import (
"mvdan.cc/sh/v3/expand" "mvdan.cc/sh/v3/expand"
) )
type snail struct{ // #type
// A Snail is a shell script interpreter instance.
type Snail struct{
runner *interp.Runner runner *interp.Runner
runtime *rt.Runtime runtime *rt.Runtime
} }
func New(rtm *rt.Runtime) *snail { func New(rtm *rt.Runtime) *Snail {
runner, _ := interp.New() runner, _ := interp.New()
return &snail{ return &Snail{
runner: runner, runner: runner,
runtime: rtm, runtime: rtm,
} }
} }
func (s *snail) Run(cmd string, strms *util.Streams) (bool, io.Writer, io.Writer, error){ func (s *Snail) Run(cmd string, strms *util.Streams) (bool, io.Writer, io.Writer, error){
file, err := syntax.NewParser().Parse(strings.NewReader(cmd), "") file, err := syntax.NewParser().Parse(strings.NewReader(cmd), "")
if err != nil { if err != nil {
return false, nil, nil, err return false, nil, nil, err

View File

@ -1,8 +1,31 @@
-- @module hilbish
local hilbish = require 'hilbish' local hilbish = require 'hilbish'
local snail = require 'snail' local snail = require 'snail'
hilbish.snail = snail.new() hilbish.snail = snail.new()
--- Runs `cmd` in Hilbish's shell script interpreter.
--- The `streams` parameter specifies the output and input streams the command should use.
--- For example, to write command output to a sink.
--- As a table, the caller can directly specify the standard output, error, and input
--- streams of the command with the table keys `out`, `err`, and `input` respectively.
--- As a boolean, it specifies whether the command should use standard output or return its output streams.
--- #example
--- -- This code is the same as `ls -l | wc -l`
--- local fs = require 'fs'
--- local pr, pw = fs.pipe()
--- hilbish.run('ls -l', {
--- stdout = pw,
--- stderr = pw,
--- })
--- pw:close()
--- hilbish.run('wc -l', {
--- stdin = pr
--- })
--- #example
-- @param cmd string
-- @param streams table|boolean
-- @returns number, string, string
function hilbish.run(cmd, streams) function hilbish.run(cmd, streams)
local sinks = {} local sinks = {}
@ -28,3 +51,26 @@ function hilbish.run(cmd, streams)
return table.unpack(returns) return table.unpack(returns)
end end
--- Sets the execution/runner mode for interactive Hilbish.
--- **NOTE: This function is deprecated and will be removed in 3.0**
--- Use `hilbish.runner.setCurrent` instead.
--- 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.
--- Read [about runner mode](../features/runner-mode) for more information.
-- @param mode string|function
function hilbish.runnerMode(mode)
if type(mode) == 'string' then
hilbish.runner.setCurrent(mode)
elseif type(mode) == 'function' then
hilbish.runner.set('_', {
run = mode
})
hilbish.runner.setCurrent '_'
else
error('expected runner mode type to be either string or function, got', type(mode))
end
end

View File

@ -72,10 +72,8 @@ end
--- Sets Hilbish's runner mode by name. --- Sets Hilbish's runner mode by name.
--- @param name string --- @param name string
function hilbish.runner.setCurrent(name) function hilbish.runner.setCurrent(name)
local r = hilbish.runner.get(name) hilbish.runner.get(name) -- throws if it doesnt exist.
currentRunner = name currentRunner = name
hilbish.runner.setMode(r.run)
end end
--- Returns the current runner by name. --- Returns the current runner by name.
@ -84,6 +82,77 @@ function hilbish.runner.getCurrent()
return currentRunner return currentRunner
end end
--- **NOTE: This function is deprecated and will be removed in 3.0**
--- Use `hilbish.runner.setCurrent` instead.
--- This is the same as the `hilbish.runnerMode` function.
--- It takes a callback, which will be used to execute all interactive input.
--- Or a string which names the runner mode to use.
-- @param mode string|function
function hilbish.runner.setMode(mode)
hilbish.runnerMode(mode)
end
local function finishExec(exitCode, input, priv)
hilbish.exitCode = exitCode
bait.throw('command.exit', exitCode, input, priv)
end
local function continuePrompt(prev, newline)
local multilinePrompt = hilbish.multiprompt()
-- the return of hilbish.read is nil when error or ctrl-d
local cont = hilbish.read(multilinePrompt)
if not cont then
return
end
if newline then
cont = '\n' .. cont
end
if cont:match '\\$' then
cont = cont:gsub('\\$', '') .. '\n'
end
return prev .. cont
end
--- Runs `input` with the currently set Hilbish runner.
--- This method is how Hilbish executes commands.
--- `priv` is an optional boolean used to state if the input should be saved to history.
-- @param input string
-- @param priv bool
function hilbish.runner.run(input, priv)
local command = hilbish.aliases.resolve(input)
bait.throw('command.preexec', input, command)
::rerun::
local runner = hilbish.runner.get(currentRunner)
local ok, out = pcall(runner.run, input)
if not ok then
io.stderr:write(out .. '\n')
finishExec(124, out.input, priv)
return
end
if out.continue then
local contInput = continuePrompt(input, out.newline)
if contInput then
input = contInput
goto rerun
end
end
if out.err then
local fields = string.split(out.err, ': ')
if fields[2] == 'not-found' or fields[2] == 'not-executable' then
bait.throw('command.' .. fields[2], fields[1])
else
io.stderr:write(out.err .. '\n')
end
end
finishExec(out.exitCode, out.input, priv)
end
function hilbish.runner.sh(input) function hilbish.runner.sh(input)
return hilbish.snail:run(input) return hilbish.snail:run(input)
end end

View File

@ -53,9 +53,7 @@ end)
*/ */
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},
"lua": {luaRunner, 1, false}, "lua": {luaRunner, 1, false},
"setMode": {hlrunnerMode, 1, false},
} }
mod := rt.NewTable() mod := rt.NewTable()
@ -64,48 +62,6 @@ func runnerModeLoader(rtm *rt.Runtime) *rt.Table {
return mod return mod
} }
// #interface runner
// setMode(cb)
// **NOTE: This function is deprecated and will be removed in 3.0**
// Use `hilbish.runner.setCurrent` instead.
// 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 (setCurrent) this will handle it.
// #param cb function
func _runnerMode() {}
// #interface runner
// sh(cmd)
// Runs a command in Hilbish's shell script interpreter.
// This is the equivalent of using `source`.
// #param cmd string
/*
func shRunner(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
if err := c.Check1Arg(); err != nil {
return nil, err
}
cmd, err := c.StringArg(0)
if err != nil {
return nil, err
}
_, exitCode, cont, newline, err := execSh(aliases.Resolve(cmd))
var luaErr rt.Value = rt.NilValue
if err != nil {
luaErr = rt.StringValue(err.Error())
}
runnerRet := rt.NewTable()
runnerRet.Set(rt.StringValue("input"), rt.StringValue(cmd))
runnerRet.Set(rt.StringValue("exitCode"), rt.IntValue(int64(exitCode)))
runnerRet.Set(rt.StringValue("continue"), rt.BoolValue(cont))
runnerRet.Set(rt.StringValue("newline"), rt.BoolValue(newline))
runnerRet.Set(rt.StringValue("err"), luaErr)
return c.PushingNext(t.Runtime, rt.TableValue(runnerRet)), nil
}
*/
// #interface runner // #interface runner
// lua(cmd) // lua(cmd)
// Evaluates `cmd` as Lua input. This is the same as using `dofile` // Evaluates `cmd` as Lua input. This is the same as using `dofile`

View File

@ -14,8 +14,7 @@ import (
var sinkMetaKey = rt.StringValue("hshsink") var sinkMetaKey = rt.StringValue("hshsink")
// #type // #type
// A sink is a structure that has input and/or output to/from // A sink is a structure that has input and/or output to/from a desination.
// a desination.
type Sink struct{ type Sink struct{
Rw *bufio.ReadWriter Rw *bufio.ReadWriter
file *os.File file *os.File