mirror of
				https://github.com/sammy-ette/Hilbish
				synced 2025-08-10 02:52:03 +00:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "f2a2ac44d64ab6fb67e9515da7ffca449d95fe81" and "8821171ff50e100121388dc03a0bbd0fcdaf3fd8" have entirely different histories.
		
	
	
		
			f2a2ac44d6
			...
			8821171ff5
		
	
		
							
								
								
									
										199
									
								
								api.go
									
									
									
									
									
								
							
							
						
						
									
										199
									
								
								api.go
									
									
									
									
									
								
							@ -4,14 +4,10 @@
 | 
				
			|||||||
package main
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"os/exec"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"runtime"
 | 
						"runtime"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"syscall"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"hilbish/util"
 | 
						"hilbish/util"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -21,18 +17,10 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var exports = map[string]lua.LGFunction {
 | 
					var exports = map[string]lua.LGFunction {
 | 
				
			||||||
	"alias": hlalias,
 | 
					 | 
				
			||||||
	"appendPath": hlappendPath,
 | 
					 | 
				
			||||||
	"cwd": hlcwd,
 | 
					 | 
				
			||||||
	"exec": hlexec,
 | 
					 | 
				
			||||||
	"flag": hlflag,
 | 
					 | 
				
			||||||
	"multiprompt": hlmlprompt,
 | 
					 | 
				
			||||||
	"prependPath": hlprependPath,
 | 
					 | 
				
			||||||
	"prompt": hlprompt,
 | 
					 | 
				
			||||||
	"interval": hlinterval,
 | 
					 | 
				
			||||||
	"read": hlread,
 | 
					 | 
				
			||||||
	"run": hlrun,
 | 
						"run": hlrun,
 | 
				
			||||||
	"timeout": hltimeout,
 | 
						"flag": hlflag,
 | 
				
			||||||
 | 
						"cwd": hlcwd,
 | 
				
			||||||
 | 
						"read": hlread,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var greeting string
 | 
					var greeting string
 | 
				
			||||||
@ -159,184 +147,3 @@ func hlread(L *lua.LState) int {
 | 
				
			|||||||
	return 1
 | 
						return 1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* prompt(str)
 | 
					 | 
				
			||||||
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 */
 | 
					 | 
				
			||||||
func hlprompt(L *lua.LState) int {
 | 
					 | 
				
			||||||
	prompt = L.CheckString(1)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// multiprompt(str)
 | 
					 | 
				
			||||||
// Changes the continued line prompt to `str`
 | 
					 | 
				
			||||||
func hlmlprompt(L *lua.LState) int {
 | 
					 | 
				
			||||||
	multilinePrompt = L.CheckString(1)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// alias(cmd, orig)
 | 
					 | 
				
			||||||
// Sets an alias of `orig` to `cmd`
 | 
					 | 
				
			||||||
func hlalias(L *lua.LState) int {
 | 
					 | 
				
			||||||
	alias := L.CheckString(1)
 | 
					 | 
				
			||||||
	source := L.CheckString(2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	aliases.Add(alias, source)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 1
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// appendPath(dir)
 | 
					 | 
				
			||||||
// Appends `dir` to $PATH
 | 
					 | 
				
			||||||
func hlappendPath(L *lua.LState) int {
 | 
					 | 
				
			||||||
	// check if dir is a table or a string
 | 
					 | 
				
			||||||
	arg := L.Get(1)
 | 
					 | 
				
			||||||
	fmt.Println(arg.Type())
 | 
					 | 
				
			||||||
	if arg.Type() == lua.LTTable {
 | 
					 | 
				
			||||||
		arg.(*lua.LTable).ForEach(func(k lua.LValue, v lua.LValue) {
 | 
					 | 
				
			||||||
			appendPath(v.String())
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	} else if arg.Type() == lua.LTString {
 | 
					 | 
				
			||||||
		appendPath(arg.String())
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		L.RaiseError("bad argument to appendPath (expected string or table, got %v)", L.Get(1).Type().String())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func appendPath(dir string) {
 | 
					 | 
				
			||||||
	dir = strings.Replace(dir, "~", curuser.HomeDir, 1)
 | 
					 | 
				
			||||||
	pathenv := os.Getenv("PATH")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// if dir isnt already in $PATH, add it
 | 
					 | 
				
			||||||
	if !strings.Contains(pathenv, dir) {
 | 
					 | 
				
			||||||
		os.Setenv("PATH", pathenv + string(os.PathListSeparator) + dir)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// exec(cmd)
 | 
					 | 
				
			||||||
// Replaces running hilbish with `cmd`
 | 
					 | 
				
			||||||
func hlexec(L *lua.LState) int {
 | 
					 | 
				
			||||||
	cmd := L.CheckString(1)
 | 
					 | 
				
			||||||
	cmdArgs, _ := splitInput(cmd)
 | 
					 | 
				
			||||||
	cmdPath, err := exec.LookPath(cmdArgs[0])
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		fmt.Println(err)
 | 
					 | 
				
			||||||
		// if we get here, cmdPath will be nothing
 | 
					 | 
				
			||||||
		// therefore nothing will run
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// syscall.Exec requires an absolute path to a binary
 | 
					 | 
				
			||||||
	// path, args, string slice of environments
 | 
					 | 
				
			||||||
	// TODO: alternative for windows
 | 
					 | 
				
			||||||
	syscall.Exec(cmdPath, cmdArgs, os.Environ())
 | 
					 | 
				
			||||||
	return 0 // random thought: does this ever return?
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// goro(fn)
 | 
					 | 
				
			||||||
// Puts `fn` in a goroutine
 | 
					 | 
				
			||||||
func hlgoroutine(L *lua.LState) int {
 | 
					 | 
				
			||||||
	fn := L.CheckFunction(1)
 | 
					 | 
				
			||||||
	argnum := L.GetTop()
 | 
					 | 
				
			||||||
	args := make([]lua.LValue, argnum)
 | 
					 | 
				
			||||||
	for i := 1; i <= argnum; i++ {
 | 
					 | 
				
			||||||
		args[i - 1] = L.Get(i)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// call fn
 | 
					 | 
				
			||||||
	go func() {
 | 
					 | 
				
			||||||
		L.CallByParam(lua.P{
 | 
					 | 
				
			||||||
			Fn:      fn,
 | 
					 | 
				
			||||||
			NRet:    0,
 | 
					 | 
				
			||||||
			Protect: true,
 | 
					 | 
				
			||||||
		}, args...)
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// timeout(cb, time)
 | 
					 | 
				
			||||||
// Runs the `cb` function after `time` in milliseconds
 | 
					 | 
				
			||||||
func hltimeout(L *lua.LState) int {
 | 
					 | 
				
			||||||
	cb := L.CheckFunction(1)
 | 
					 | 
				
			||||||
	ms := L.CheckInt(2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	timeout := time.Duration(ms) * time.Millisecond
 | 
					 | 
				
			||||||
	time.Sleep(timeout)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	L.CallByParam(lua.P{
 | 
					 | 
				
			||||||
		Fn:      cb,
 | 
					 | 
				
			||||||
		NRet:    0,
 | 
					 | 
				
			||||||
		Protect: true,
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// interval(cb, time)
 | 
					 | 
				
			||||||
// Runs the `cb` function every `time` milliseconds
 | 
					 | 
				
			||||||
func hlinterval(L *lua.LState) int {
 | 
					 | 
				
			||||||
	intervalfunc := L.CheckFunction(1)
 | 
					 | 
				
			||||||
	ms := L.CheckInt(2)
 | 
					 | 
				
			||||||
	interval := time.Duration(ms) * time.Millisecond
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ticker := time.NewTicker(interval)
 | 
					 | 
				
			||||||
	stop := make(chan lua.LValue)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	go func() {
 | 
					 | 
				
			||||||
		for {
 | 
					 | 
				
			||||||
			select {
 | 
					 | 
				
			||||||
			case <-ticker.C:
 | 
					 | 
				
			||||||
				if err := L.CallByParam(lua.P{
 | 
					 | 
				
			||||||
					Fn: intervalfunc,
 | 
					 | 
				
			||||||
					NRet: 0,
 | 
					 | 
				
			||||||
					Protect: true,
 | 
					 | 
				
			||||||
				}); err != nil {
 | 
					 | 
				
			||||||
					fmt.Fprintln(os.Stderr, "Error in interval function:\n\n", err)
 | 
					 | 
				
			||||||
					stop <- lua.LTrue // stop the interval
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			case <-stop:
 | 
					 | 
				
			||||||
				ticker.Stop()
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	L.Push(lua.LChannel(stop))
 | 
					 | 
				
			||||||
	return 1
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 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 the entries to complete.
 | 
					 | 
				
			||||||
// Nested tables will be used as sub-completions.
 | 
					 | 
				
			||||||
func hlcomplete(L *lua.LState) int {
 | 
					 | 
				
			||||||
	scope := L.CheckString(1)
 | 
					 | 
				
			||||||
	cb := L.CheckFunction(2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	luaCompletions[scope] = cb
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// prependPath(dir)
 | 
					 | 
				
			||||||
// Prepends `dir` to $PATH
 | 
					 | 
				
			||||||
func hlprependPath(L *lua.LState) int {
 | 
					 | 
				
			||||||
	dir := L.CheckString(1)
 | 
					 | 
				
			||||||
	dir = strings.Replace(dir, "~", curuser.HomeDir, 1)
 | 
					 | 
				
			||||||
	pathenv := os.Getenv("PATH")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// if dir isnt already in $PATH, add in
 | 
					 | 
				
			||||||
	if !strings.Contains(pathenv, dir) {
 | 
					 | 
				
			||||||
		os.Setenv("PATH", dir + string(os.PathListSeparator) + pathenv)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										29
									
								
								docs/global.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								docs/global.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					alias(cmd, orig) > Sets an alias of `orig` to `cmd`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 the entries to complete.
 | 
				
			||||||
 | 
					Nested tables will be used as sub-completions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exec(cmd) > Replaces running hilbish with `cmd`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					goro(fn) > Puts `fn` in a goroutine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interval(cb, time) > Runs the `cb` function every `time` milliseconds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					multiprompt(str) > Changes the continued line prompt to `str`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					prependPath(dir) > Prepends `dir` to $PATH
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 prompt(str) > 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					timeout(cb, time) > Runs the `cb` function after `time` in milliseconds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1,39 +1,10 @@
 | 
				
			|||||||
alias(cmd, orig) > Sets an alias of `orig` to `cmd`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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 the entries to complete.
 | 
					 | 
				
			||||||
Nested tables will be used as sub-completions.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
cwd() > Returns the current directory of the shell
 | 
					cwd() > Returns the current directory of the shell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exec(cmd) > Replaces running hilbish with `cmd`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
flag(f) > Checks if the `f` flag has been passed to Hilbish.
 | 
					flag(f) > Checks if the `f` flag has been passed to Hilbish.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
goro(fn) > Puts `fn` in a goroutine
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interval(cb, time) > Runs the `cb` function every `time` milliseconds
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
multiprompt(str) > Changes the continued line prompt to `str`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
prependPath(dir) > Prepends `dir` to $PATH
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 prompt(str) > 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.
 | 
					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.
 | 
					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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
run(cmd) > Runs `cmd` in Hilbish's sh interpreter.
 | 
					run(cmd) > Runs `cmd` in Hilbish's sh interpreter
 | 
				
			||||||
 | 
					 | 
				
			||||||
timeout(cb, time) > Runs the `cb` function after `time` in milliseconds
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,3 @@
 | 
				
			|||||||
+ `signal.sigint` > Sent when Hilbish receives SIGINT (on Ctrl-C).
 | 
					+ `signal.sigint` > Sent when Hilbish receives SIGINT (used to Ctrl-C).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
+ `signal.resize` > Sent when the terminal is resized.
 | 
					+ `signal.resize` > Sent when the terminal is resized.
 | 
				
			||||||
+ `signal.sigusr1`
 | 
					 | 
				
			||||||
+ `signal.sigusr2`
 | 
					 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										173
									
								
								lua.go
									
									
									
									
									
								
							
							
						
						
									
										173
									
								
								lua.go
									
									
									
									
									
								
							@ -3,6 +3,10 @@ package main
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
						"os/exec"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"hilbish/golibs/bait"
 | 
						"hilbish/golibs/bait"
 | 
				
			||||||
	"hilbish/golibs/commander"
 | 
						"hilbish/golibs/commander"
 | 
				
			||||||
@ -10,6 +14,7 @@ import (
 | 
				
			|||||||
	"hilbish/golibs/terminal"
 | 
						"hilbish/golibs/terminal"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/yuin/gopher-lua"
 | 
						"github.com/yuin/gopher-lua"
 | 
				
			||||||
 | 
						"layeh.com/gopher-luar"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var minimalconf = `prompt '& '`
 | 
					var minimalconf = `prompt '& '`
 | 
				
			||||||
@ -18,6 +23,16 @@ func luaInit() {
 | 
				
			|||||||
	l = lua.NewState()
 | 
						l = lua.NewState()
 | 
				
			||||||
	l.OpenLibs()
 | 
						l.OpenLibs()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						l.SetGlobal("prompt", l.NewFunction(hshprompt))
 | 
				
			||||||
 | 
						l.SetGlobal("multiprompt", l.NewFunction(hshmlprompt))
 | 
				
			||||||
 | 
						l.SetGlobal("alias", l.NewFunction(hshalias))
 | 
				
			||||||
 | 
						l.SetGlobal("appendPath", l.NewFunction(hshappendPath))
 | 
				
			||||||
 | 
						l.SetGlobal("prependPath", l.NewFunction(hshprependPath))
 | 
				
			||||||
 | 
						l.SetGlobal("exec", l.NewFunction(hshexec))
 | 
				
			||||||
 | 
						l.SetGlobal("goro", luar.New(l, hshgoroutine))
 | 
				
			||||||
 | 
						l.SetGlobal("timeout", luar.New(l, hshtimeout))
 | 
				
			||||||
 | 
						l.SetGlobal("interval", l.NewFunction(hshinterval))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// yes this is stupid, i know
 | 
						// yes this is stupid, i know
 | 
				
			||||||
	l.PreloadModule("hilbish", hilbishLoader)
 | 
						l.PreloadModule("hilbish", hilbishLoader)
 | 
				
			||||||
	l.DoString("hilbish = require 'hilbish'")
 | 
						l.DoString("hilbish = require 'hilbish'")
 | 
				
			||||||
@ -46,7 +61,7 @@ func luaInit() {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	l.SetGlobal("complete", l.NewFunction(hlcomplete))
 | 
						l.SetGlobal("complete", l.NewFunction(hshcomplete))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add more paths that Lua can require from
 | 
						// Add more paths that Lua can require from
 | 
				
			||||||
	l.DoString("package.path = package.path .. " + requirePaths)
 | 
						l.DoString("package.path = package.path .. " + requirePaths)
 | 
				
			||||||
@ -87,3 +102,159 @@ func runLogin() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* prompt(str)
 | 
				
			||||||
 | 
					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 */
 | 
				
			||||||
 | 
					func hshprompt(L *lua.LState) int {
 | 
				
			||||||
 | 
						prompt = L.CheckString(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// multiprompt(str)
 | 
				
			||||||
 | 
					// Changes the continued line prompt to `str`
 | 
				
			||||||
 | 
					func hshmlprompt(L *lua.LState) int {
 | 
				
			||||||
 | 
						multilinePrompt = L.CheckString(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// alias(cmd, orig)
 | 
				
			||||||
 | 
					// Sets an alias of `orig` to `cmd`
 | 
				
			||||||
 | 
					func hshalias(L *lua.LState) int {
 | 
				
			||||||
 | 
						alias := L.CheckString(1)
 | 
				
			||||||
 | 
						source := L.CheckString(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						aliases.Add(alias, source)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// appendPath(dir)
 | 
				
			||||||
 | 
					// Appends `dir` to $PATH
 | 
				
			||||||
 | 
					func hshappendPath(L *lua.LState) int {
 | 
				
			||||||
 | 
						// check if dir is a table or a string
 | 
				
			||||||
 | 
						arg := L.Get(1)
 | 
				
			||||||
 | 
						fmt.Println(arg.Type())
 | 
				
			||||||
 | 
						if arg.Type() == lua.LTTable {
 | 
				
			||||||
 | 
							arg.(*lua.LTable).ForEach(func(k lua.LValue, v lua.LValue) {
 | 
				
			||||||
 | 
								appendPath(v.String())
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						} else if arg.Type() == lua.LTString {
 | 
				
			||||||
 | 
							appendPath(arg.String())
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							L.RaiseError("bad argument to appendPath (expected string or table, got %v)", L.Get(1).Type().String())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func appendPath(dir string) {
 | 
				
			||||||
 | 
						dir = strings.Replace(dir, "~", curuser.HomeDir, 1)
 | 
				
			||||||
 | 
						pathenv := os.Getenv("PATH")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// if dir isnt already in $PATH, add it
 | 
				
			||||||
 | 
						if !strings.Contains(pathenv, dir) {
 | 
				
			||||||
 | 
							os.Setenv("PATH", pathenv + string(os.PathListSeparator) + dir)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// exec(cmd)
 | 
				
			||||||
 | 
					// Replaces running hilbish with `cmd`
 | 
				
			||||||
 | 
					func hshexec(L *lua.LState) int {
 | 
				
			||||||
 | 
						cmd := L.CheckString(1)
 | 
				
			||||||
 | 
						cmdArgs, _ := splitInput(cmd)
 | 
				
			||||||
 | 
						cmdPath, err := exec.LookPath(cmdArgs[0])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							fmt.Println(err)
 | 
				
			||||||
 | 
							// if we get here, cmdPath will be nothing
 | 
				
			||||||
 | 
							// therefore nothing will run
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// syscall.Exec requires an absolute path to a binary
 | 
				
			||||||
 | 
						// path, args, string slice of environments
 | 
				
			||||||
 | 
						// TODO: alternative for windows
 | 
				
			||||||
 | 
						syscall.Exec(cmdPath, cmdArgs, os.Environ())
 | 
				
			||||||
 | 
						return 0 // random thought: does this ever return?
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// goro(fn)
 | 
				
			||||||
 | 
					// Puts `fn` in a goroutine
 | 
				
			||||||
 | 
					func hshgoroutine(gofunc func()) {
 | 
				
			||||||
 | 
						go gofunc()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// timeout(cb, time)
 | 
				
			||||||
 | 
					// Runs the `cb` function after `time` in milliseconds
 | 
				
			||||||
 | 
					func hshtimeout(timeoutfunc func(), ms int) {
 | 
				
			||||||
 | 
						timeout := time.Duration(ms) * time.Millisecond
 | 
				
			||||||
 | 
						time.Sleep(timeout)
 | 
				
			||||||
 | 
						timeoutfunc()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// interval(cb, time)
 | 
				
			||||||
 | 
					// Runs the `cb` function every `time` milliseconds
 | 
				
			||||||
 | 
					func hshinterval(L *lua.LState) int {
 | 
				
			||||||
 | 
						intervalfunc := L.CheckFunction(1)
 | 
				
			||||||
 | 
						ms := L.CheckInt(2)
 | 
				
			||||||
 | 
						interval := time.Duration(ms) * time.Millisecond
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ticker := time.NewTicker(interval)
 | 
				
			||||||
 | 
						stop := make(chan lua.LValue)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case <-ticker.C:
 | 
				
			||||||
 | 
									if err := L.CallByParam(lua.P{
 | 
				
			||||||
 | 
										Fn: intervalfunc,
 | 
				
			||||||
 | 
										NRet: 0,
 | 
				
			||||||
 | 
										Protect: true,
 | 
				
			||||||
 | 
									}); err != nil {
 | 
				
			||||||
 | 
										fmt.Fprintln(os.Stderr, "Error in interval function:\n\n", err)
 | 
				
			||||||
 | 
										stop <- lua.LTrue // stop the interval
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								case <-stop:
 | 
				
			||||||
 | 
									ticker.Stop()
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						L.Push(lua.LChannel(stop))
 | 
				
			||||||
 | 
						return 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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 the entries to complete.
 | 
				
			||||||
 | 
					// Nested tables will be used as sub-completions.
 | 
				
			||||||
 | 
					func hshcomplete(L *lua.LState) int {
 | 
				
			||||||
 | 
						scope := L.CheckString(1)
 | 
				
			||||||
 | 
						cb := L.CheckFunction(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						luaCompletions[scope] = cb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// prependPath(dir)
 | 
				
			||||||
 | 
					// Prepends `dir` to $PATH
 | 
				
			||||||
 | 
					func hshprependPath(L *lua.LState) int {
 | 
				
			||||||
 | 
						dir := L.CheckString(1)
 | 
				
			||||||
 | 
						dir = strings.Replace(dir, "~", curuser.HomeDir, 1)
 | 
				
			||||||
 | 
						pathenv := os.Getenv("PATH")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// if dir isnt already in $PATH, add in
 | 
				
			||||||
 | 
						if !strings.Contains(pathenv, dir) {
 | 
				
			||||||
 | 
							os.Setenv("PATH", dir + string(os.PathListSeparator) + pathenv)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								main.go
									
									
									
									
									
								
							@ -260,22 +260,20 @@ func fmtPrompt() string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func handleSignals() {
 | 
					func handleSignals() {
 | 
				
			||||||
	c := make(chan os.Signal)
 | 
						c := make(chan os.Signal)
 | 
				
			||||||
	signal.Notify(c, os.Interrupt, syscall.SIGWINCH, syscall.SIGUSR1, syscall.SIGUSR2)
 | 
						signal.Notify(c, os.Interrupt, syscall.SIGWINCH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for s := range c {
 | 
						for s := range c {
 | 
				
			||||||
		switch s {
 | 
							switch s {
 | 
				
			||||||
		case os.Interrupt:
 | 
							case os.Interrupt:
 | 
				
			||||||
			hooks.Em.Emit("signal.sigint")
 | 
								hooks.Em.Emit("signals.sigint")
 | 
				
			||||||
			if !running && interactive {
 | 
								if !running && interactive {
 | 
				
			||||||
				lr.ClearInput()
 | 
									lr.ClearInput()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case syscall.SIGWINCH:
 | 
							case syscall.SIGWINCH:
 | 
				
			||||||
			hooks.Em.Emit("signal.resize")
 | 
								hooks.Em.Emit("signals.resize")
 | 
				
			||||||
			if !running && interactive {
 | 
								if !running && interactive {
 | 
				
			||||||
				lr.Resize()
 | 
									lr.Resize()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case syscall.SIGUSR1: hooks.Em.Emit("signal.sigusr1")
 | 
					 | 
				
			||||||
		case syscall.SIGUSR2: hooks.Em.Emit("signal.sigusr2")
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user