mirror of https://github.com/Hilbis/Hilbish
Compare commits
10 Commits
409f3f734e
...
86afa0c3e2
Author | SHA1 | Date |
---|---|---|
sammyette | 86afa0c3e2 | |
sammyette | 40c3cecabb | |
sammyette | ce99209f0d | |
sammyette | d1dbb84c16 | |
sammyette | 5b84718021 | |
sammyette | 3d727e6411 | |
sammyette | 7d487bfc98 | |
sammyette | 11fc1edd94 | |
sammyette | b416264138 | |
sammyette | eded38c7b5 |
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -1,14 +1,22 @@
|
||||||
# 🎀 Changelog
|
# 🎀 Changelog
|
||||||
|
|
||||||
## Unreleased
|
## [2.2.2] - 2024-04-16
|
||||||
## Added
|
### Fixed
|
||||||
|
- Line refresh fixes (less flicker)
|
||||||
|
- Do more checks for a TTY
|
||||||
|
- Panic if ENOTTY is thrown from readline
|
||||||
|
- use `x/term` function to check if a terminal
|
||||||
|
|
||||||
|
### Added
|
||||||
- Page Up/Down keybinds for Greenhouse will now scroll up and down the size of the region (a page)
|
- Page Up/Down keybinds for Greenhouse will now scroll up and down the size of the region (a page)
|
||||||
|
|
||||||
## Changed
|
### Changed
|
||||||
- Remove usage of `hilbish.goro` in Greenhouse.
|
- Remove usage of `hilbish.goro` in Greenhouse.
|
||||||
|
- Values in `hilbish` table are no longer protected. This means
|
||||||
|
they can be overridden. (#287)
|
||||||
|
|
||||||
## [2.2.1] - 2023-12-26
|
## [2.2.1] - 2023-12-26
|
||||||
## Fixed
|
### Fixed
|
||||||
- Removed a left over debug print
|
- Removed a left over debug print
|
||||||
- Recover panic in `hilbish.goro`
|
- Recover panic in `hilbish.goro`
|
||||||
|
|
||||||
|
|
61
api.go
61
api.go
|
@ -59,47 +59,8 @@ var hilbishLoader = packagelib.Loader{
|
||||||
}
|
}
|
||||||
|
|
||||||
func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
|
func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
|
||||||
fakeMod := rt.NewTable()
|
|
||||||
modmt := rt.NewTable()
|
|
||||||
mod := rt.NewTable()
|
mod := rt.NewTable()
|
||||||
|
|
||||||
modIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|
||||||
arg := c.Arg(1)
|
|
||||||
val := mod.Get(arg)
|
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, val), nil
|
|
||||||
}
|
|
||||||
modNewIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|
||||||
k, err := c.StringArg(1)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
v := c.Arg(2)
|
|
||||||
if k == "highlighter" {
|
|
||||||
var err error
|
|
||||||
// fine to assign, since itll be either nil or a closure
|
|
||||||
highlighter, err = c.ClosureArg(2)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("hilbish.highlighter has to be a function")
|
|
||||||
}
|
|
||||||
} else if k == "hinter" {
|
|
||||||
var err error
|
|
||||||
hinter, err = c.ClosureArg(2)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("hilbish.hinter has to be a function")
|
|
||||||
}
|
|
||||||
} else if modVal := mod.Get(rt.StringValue(k)); modVal != rt.NilValue {
|
|
||||||
return nil, errors.New("not allowed to override in hilbish table")
|
|
||||||
}
|
|
||||||
mod.Set(rt.StringValue(k), v)
|
|
||||||
|
|
||||||
return c.Next(), nil
|
|
||||||
}
|
|
||||||
modmt.Set(rt.StringValue("__newindex"), rt.FunctionValue(rt.NewGoFunction(modNewIndex, "__newindex", 3, false)))
|
|
||||||
modmt.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(modIndex, "__index", 2, false)))
|
|
||||||
fakeMod.SetMetatable(modmt)
|
|
||||||
|
|
||||||
util.SetExports(rtm, mod, exports)
|
util.SetExports(rtm, mod, exports)
|
||||||
hshMod = mod
|
hshMod = mod
|
||||||
|
|
||||||
|
@ -110,16 +71,16 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
|
||||||
username = strings.Split(username, "\\")[1] // for some reason Username includes the hostname on windows
|
username = strings.Split(username, "\\")[1] // for some reason Username includes the hostname on windows
|
||||||
}
|
}
|
||||||
|
|
||||||
util.SetFieldProtected(fakeMod, mod, "ver", rt.StringValue(getVersion()))
|
util.SetField(rtm, mod, "ver", rt.StringValue(getVersion()))
|
||||||
util.SetFieldProtected(fakeMod, mod, "goVersion", rt.StringValue(runtime.Version()))
|
util.SetField(rtm, mod, "goVersion", rt.StringValue(runtime.Version()))
|
||||||
util.SetFieldProtected(fakeMod, mod, "user", rt.StringValue(username))
|
util.SetField(rtm, mod, "user", rt.StringValue(username))
|
||||||
util.SetFieldProtected(fakeMod, mod, "host", rt.StringValue(host))
|
util.SetField(rtm, mod, "host", rt.StringValue(host))
|
||||||
util.SetFieldProtected(fakeMod, mod, "home", rt.StringValue(curuser.HomeDir))
|
util.SetField(rtm, mod, "home", rt.StringValue(curuser.HomeDir))
|
||||||
util.SetFieldProtected(fakeMod, mod, "dataDir", rt.StringValue(dataDir))
|
util.SetField(rtm, mod, "dataDir", rt.StringValue(dataDir))
|
||||||
util.SetFieldProtected(fakeMod, mod, "interactive", rt.BoolValue(interactive))
|
util.SetField(rtm, mod, "interactive", rt.BoolValue(interactive))
|
||||||
util.SetFieldProtected(fakeMod, mod, "login", rt.BoolValue(login))
|
util.SetField(rtm, mod, "login", rt.BoolValue(login))
|
||||||
util.SetFieldProtected(fakeMod, mod, "vimMode", rt.NilValue)
|
util.SetField(rtm, mod, "vimMode", rt.NilValue)
|
||||||
util.SetFieldProtected(fakeMod, mod, "exitCode", rt.IntValue(0))
|
util.SetField(rtm, mod, "exitCode", rt.IntValue(0))
|
||||||
|
|
||||||
// hilbish.userDir table
|
// hilbish.userDir table
|
||||||
hshuser := userDirLoader(rtm)
|
hshuser := userDirLoader(rtm)
|
||||||
|
@ -171,7 +132,7 @@ func hilbishLoad(rtm *rt.Runtime) (rt.Value, func()) {
|
||||||
pluginModule := moduleLoader(rtm)
|
pluginModule := moduleLoader(rtm)
|
||||||
mod.Set(rt.StringValue("module"), rt.TableValue(pluginModule))
|
mod.Set(rt.StringValue("module"), rt.TableValue(pluginModule))
|
||||||
|
|
||||||
return rt.TableValue(fakeMod), nil
|
return rt.TableValue(mod), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getenv(key, fallback string) string {
|
func getenv(key, fallback string) string {
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -1,6 +1,6 @@
|
||||||
module hilbish
|
module hilbish
|
||||||
|
|
||||||
go 1.17
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/arnodel/golua v0.0.0-20220221163911-dfcf252b6f86
|
github.com/arnodel/golua v0.0.0-20220221163911-dfcf252b6f86
|
||||||
|
|
10
main.go
10
main.go
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
@ -9,6 +10,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"hilbish/util"
|
"hilbish/util"
|
||||||
"hilbish/golibs/bait"
|
"hilbish/golibs/bait"
|
||||||
|
@ -88,7 +90,7 @@ func main() {
|
||||||
interactive = true
|
interactive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileInfo, _ := os.Stdin.Stat(); (fileInfo.Mode() & os.ModeCharDevice) == 0 {
|
if fileInfo, _ := os.Stdin.Stat(); (fileInfo.Mode() & os.ModeCharDevice) == 0 || !term.IsTerminal(int(os.Stdin.Fd())) {
|
||||||
interactive = false
|
interactive = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,8 +191,12 @@ input:
|
||||||
} else {
|
} else {
|
||||||
// If we get a completely random error, print
|
// If we get a completely random error, print
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
if errors.Is(err, syscall.ENOTTY) {
|
||||||
|
// what are we even doing here?
|
||||||
|
panic("not a tty")
|
||||||
|
}
|
||||||
|
<-make(chan struct{})
|
||||||
}
|
}
|
||||||
// TODO: Halt if any other error occurs
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var priv bool
|
var priv bool
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
local fs = require 'fs'
|
||||||
|
|
||||||
|
-- explanation: this specific function gives to us info about
|
||||||
|
-- the currently running source. this includes a path to the
|
||||||
|
-- source file (info.source)
|
||||||
|
-- we will use that to automatically load all commands by reading
|
||||||
|
-- all the files in this dir and just requiring it.
|
||||||
|
local info = debug.getinfo(1)
|
||||||
|
local commandDir = fs.dir(info.source)
|
||||||
|
if commandDir == '.' then return end
|
||||||
|
|
||||||
|
local commands = fs.readdir(commandDir)
|
||||||
|
for _, command in ipairs(commands) do
|
||||||
|
local name = command:gsub('%.lua', '') -- chop off extension
|
||||||
|
if name ~= 'init' then
|
||||||
|
-- skip this file (for obvious reasons)
|
||||||
|
require('nature.completions.' .. name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function hilbish.completion.handler(line, pos)
|
function hilbish.completion.handler(line, pos)
|
||||||
if type(line) ~= 'string' then error '#1 must be a string' end
|
if type(line) ~= 'string' then error '#1 must be a string' end
|
||||||
if type(pos) ~= 'number' then error '#2 must be a number' end
|
if type(pos) ~= 'number' then error '#2 must be a number' end
|
|
@ -0,0 +1,53 @@
|
||||||
|
local function curry(f)
|
||||||
|
return function (x) return function (y) return f(x,y) end end
|
||||||
|
end
|
||||||
|
|
||||||
|
local flags = {}
|
||||||
|
local function flag(f, description)
|
||||||
|
flags[f] = {description}
|
||||||
|
end
|
||||||
|
|
||||||
|
local addflag = curry(flag)
|
||||||
|
|
||||||
|
addflag '-A' 'Ask for password via askpass or $SUDO_ASKPASS'
|
||||||
|
addflag '-B' 'Ring the bell as part of the password prompt.'
|
||||||
|
|
||||||
|
hilbish.complete('command.sudo', function(query, ctx, fields)
|
||||||
|
table.remove(fields, 1)
|
||||||
|
local nonflags = table.filter(fields, function(v)
|
||||||
|
if v == '' then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return v:match '^%-' == nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
if #fields == 1 or #nonflags == 0 then
|
||||||
|
-- complete commands or sudo flags
|
||||||
|
if query:match ('^%-') then
|
||||||
|
local compFlags = {}
|
||||||
|
for flg, flgstuff in pairs(flags) do
|
||||||
|
if flg:match('^' .. query) then
|
||||||
|
compFlags[flg] = flgstuff
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local compGroup = {
|
||||||
|
items = compFlags,
|
||||||
|
type = 'list'
|
||||||
|
}
|
||||||
|
|
||||||
|
return {compGroup}, query
|
||||||
|
end
|
||||||
|
|
||||||
|
local comps, pfx = hilbish.completion.bins(query, ctx, fields)
|
||||||
|
local compGroup = {
|
||||||
|
items = comps,
|
||||||
|
type = 'grid'
|
||||||
|
}
|
||||||
|
|
||||||
|
return {compGroup}, pfx
|
||||||
|
end
|
||||||
|
|
||||||
|
-- otherwise, get command flags
|
||||||
|
return hilbish.completion.call('command.' .. fields[2], query, ctx, fields)
|
||||||
|
end)
|
|
@ -1,21 +1,7 @@
|
||||||
local opts = {}
|
|
||||||
hilbish.opts = {}
|
hilbish.opts = {}
|
||||||
|
|
||||||
setmetatable(hilbish.opts, {
|
|
||||||
__newindex = function(_, k, v)
|
|
||||||
if opts[k] == nil then
|
|
||||||
error(string.format('opt %s does not exist', k))
|
|
||||||
end
|
|
||||||
|
|
||||||
opts[k] = v
|
|
||||||
end,
|
|
||||||
__index = function(_, k)
|
|
||||||
return opts[k]
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
local function setupOpt(name, default)
|
local function setupOpt(name, default)
|
||||||
opts[name] = default
|
hilbish.opts[name] = default
|
||||||
pcall(require, 'nature.opts.' .. name)
|
pcall(require, 'nature.opts.' .. name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,8 @@ const (
|
||||||
seqCursorTopLeft = "\x1b[H" // Clears screen and places cursor on top-left
|
seqCursorTopLeft = "\x1b[H" // Clears screen and places cursor on top-left
|
||||||
|
|
||||||
seqGetCursorPos = "\x1b6n" // response: "\x1b{Line};{Column}R"
|
seqGetCursorPos = "\x1b6n" // response: "\x1b{Line};{Column}R"
|
||||||
|
seqHideCursor = "\x1b[?25l"
|
||||||
|
seqUnhideCursor = "\x1b[?25h"
|
||||||
|
|
||||||
seqCtrlLeftArrow = "\x1b[1;5D"
|
seqCtrlLeftArrow = "\x1b[1;5D"
|
||||||
seqCtrlRightArrow = "\x1b[1;5C"
|
seqCtrlRightArrow = "\x1b[1;5C"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package readline
|
package readline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
// "fmt"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -68,6 +69,40 @@ func (rl *Instance) getCursorPos() (x int, y int) {
|
||||||
// This means that they are not used to keep any reference point when
|
// This means that they are not used to keep any reference point when
|
||||||
// when we internally move around clearning and printing things
|
// when we internally move around clearning and printing things
|
||||||
|
|
||||||
|
/*
|
||||||
|
func moveCursorUpBuffered(i int) {
|
||||||
|
if i < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(rl.bufferedOut, "\x1b[%dA", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveCursorDownBuffered(i int) {
|
||||||
|
if i < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(rl.bufferedOut, "\x1b[%dB", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveCursorForwardsBuffered(i int) {
|
||||||
|
if i < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(rl.bufferedOut, "\x1b[%dC", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveCursorUpBuffered(i int) {
|
||||||
|
if i < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(rl.bufferedOut, "\x1b[%dD", i)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func moveCursorUp(i int) {
|
func moveCursorUp(i int) {
|
||||||
if i < 1 {
|
if i < 1 {
|
||||||
return
|
return
|
||||||
|
@ -100,6 +135,14 @@ func moveCursorBackwards(i int) {
|
||||||
printf("\x1b[%dD", i)
|
printf("\x1b[%dD", i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hideCursor() {
|
||||||
|
print(seqHideCursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func unhideCursor() {
|
||||||
|
print(seqUnhideCursor)
|
||||||
|
}
|
||||||
|
|
||||||
func (rl *Instance) backspace(forward bool) {
|
func (rl *Instance) backspace(forward bool) {
|
||||||
if len(rl.line) == 0 || rl.pos == 0 {
|
if len(rl.line) == 0 || rl.pos == 0 {
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module github.com/maxlandon/readline
|
module github.com/maxlandon/readline
|
||||||
|
|
||||||
go 1.16
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package readline
|
package readline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -203,6 +204,8 @@ type Instance struct {
|
||||||
ViActionCallback func(ViAction, []string)
|
ViActionCallback func(ViAction, []string)
|
||||||
|
|
||||||
RawInputCallback func([]rune) // called on all input
|
RawInputCallback func([]rune) // called on all input
|
||||||
|
|
||||||
|
bufferedOut *bufio.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInstance is used to create a readline instance and initialise it with sane defaults.
|
// NewInstance is used to create a readline instance and initialise it with sane defaults.
|
||||||
|
@ -251,6 +254,8 @@ func NewInstance() *Instance {
|
||||||
return suggs
|
return suggs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rl.bufferedOut = bufio.NewWriter(os.Stdout)
|
||||||
|
|
||||||
// Registers
|
// Registers
|
||||||
rl.initRegisters()
|
rl.initRegisters()
|
||||||
|
|
||||||
|
|
|
@ -33,19 +33,20 @@ func (rl *Instance) GetLine() []rune {
|
||||||
func (rl *Instance) echo() {
|
func (rl *Instance) echo() {
|
||||||
|
|
||||||
// Then we print the prompt, and the line,
|
// Then we print the prompt, and the line,
|
||||||
|
hideCursor()
|
||||||
switch {
|
switch {
|
||||||
case rl.PasswordMask != 0:
|
case rl.PasswordMask != 0:
|
||||||
case rl.PasswordMask > 0:
|
case rl.PasswordMask > 0:
|
||||||
print(strings.Repeat(string(rl.PasswordMask), len(rl.line)) + " ")
|
rl.bufprint(strings.Repeat(string(rl.PasswordMask), len(rl.line)) + " ")
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
// Go back to prompt position, and clear everything below
|
// Go back to prompt position, and clear everything below
|
||||||
moveCursorBackwards(GetTermWidth())
|
moveCursorBackwards(GetTermWidth())
|
||||||
moveCursorUp(rl.posY)
|
moveCursorUp(rl.posY)
|
||||||
print(seqClearScreenBelow)
|
|
||||||
|
|
||||||
// Print the prompt
|
// Print the prompt
|
||||||
print(string(rl.realPrompt))
|
rl.bufprint(string(rl.realPrompt))
|
||||||
|
|
||||||
// Assemble the line, taking virtual completions into account
|
// Assemble the line, taking virtual completions into account
|
||||||
var line []rune
|
var line []rune
|
||||||
|
@ -57,11 +58,14 @@ func (rl *Instance) echo() {
|
||||||
|
|
||||||
// Print the input line with optional syntax highlighting
|
// Print the input line with optional syntax highlighting
|
||||||
if rl.SyntaxHighlighter != nil {
|
if rl.SyntaxHighlighter != nil {
|
||||||
print(rl.SyntaxHighlighter(line))
|
rl.bufprint(rl.SyntaxHighlighter(line))
|
||||||
} else {
|
} else {
|
||||||
print(string(line))
|
rl.bufprint(string(line))
|
||||||
}
|
}
|
||||||
|
rl.bufprint(seqClearScreenBelow)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
rl.bufflush()
|
||||||
|
|
||||||
// Update references with new coordinates only now, because
|
// Update references with new coordinates only now, because
|
||||||
// the new line may be longer/shorter than the previous one.
|
// the new line may be longer/shorter than the previous one.
|
||||||
|
@ -72,6 +76,7 @@ func (rl *Instance) echo() {
|
||||||
moveCursorUp(rl.fullY)
|
moveCursorUp(rl.fullY)
|
||||||
moveCursorDown(rl.posY)
|
moveCursorDown(rl.posY)
|
||||||
moveCursorForwards(rl.posX)
|
moveCursorForwards(rl.posX)
|
||||||
|
unhideCursor()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) insert(r []rune) {
|
func (rl *Instance) insert(r []rune) {
|
||||||
|
@ -159,7 +164,7 @@ func (rl *Instance) clearLine() {
|
||||||
moveCursorForwards(rl.promptLen)
|
moveCursorForwards(rl.promptLen)
|
||||||
|
|
||||||
// Clear everything after & below the cursor
|
// Clear everything after & below the cursor
|
||||||
print(seqClearScreenBelow)
|
//print(seqClearScreenBelow)
|
||||||
|
|
||||||
// Real input line
|
// Real input line
|
||||||
rl.line = []rune{}
|
rl.line = []rune{}
|
||||||
|
|
|
@ -48,7 +48,7 @@ func (rl *Instance) RefreshPromptLog(log string) (err error) {
|
||||||
rl.stillOnRefresh = true
|
rl.stillOnRefresh = true
|
||||||
moveCursorUp(rl.infoY + rl.tcUsedY)
|
moveCursorUp(rl.infoY + rl.tcUsedY)
|
||||||
moveCursorBackwards(GetTermWidth())
|
moveCursorBackwards(GetTermWidth())
|
||||||
print("\r\n" + seqClearScreenBelow)
|
//print("\r\n" + seqClearScreenBelow)
|
||||||
|
|
||||||
// Print the log
|
// Print the log
|
||||||
fmt.Printf(log)
|
fmt.Printf(log)
|
||||||
|
@ -97,7 +97,7 @@ func (rl *Instance) RefreshPromptInPlace(prompt string) (err error) {
|
||||||
print(seqClearLine)
|
print(seqClearLine)
|
||||||
moveCursorUp(rl.infoY + rl.tcUsedY)
|
moveCursorUp(rl.infoY + rl.tcUsedY)
|
||||||
moveCursorBackwards(GetTermWidth())
|
moveCursorBackwards(GetTermWidth())
|
||||||
print("\r\n" + seqClearScreenBelow)
|
//print("\r\n" + seqClearScreenBelow)
|
||||||
|
|
||||||
// Add a new line if needed
|
// Add a new line if needed
|
||||||
if rl.Multiline {
|
if rl.Multiline {
|
||||||
|
@ -137,7 +137,7 @@ func (rl *Instance) RefreshPromptCustom(prompt string, offset int, clearLine boo
|
||||||
moveCursorUp(offset)
|
moveCursorUp(offset)
|
||||||
|
|
||||||
// Then clear everything below our new position
|
// Then clear everything below our new position
|
||||||
print(seqClearScreenBelow)
|
//print(seqClearScreenBelow)
|
||||||
|
|
||||||
// Update the prompt if a special has been passed.
|
// Update the prompt if a special has been passed.
|
||||||
if prompt != "" {
|
if prompt != "" {
|
||||||
|
|
|
@ -868,7 +868,7 @@ func (rl *Instance) escapeSeq(r []rune) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !rl.mainHist {
|
if !rl.mainHist && rl.altHistory != nil {
|
||||||
line, err = rl.altHistory.GetLine(rl.altHistory.Len() - 1)
|
line, err = rl.altHistory.GetLine(rl.altHistory.Len() - 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
|
@ -276,13 +276,14 @@ func (rl *Instance) writeTabCompletion() {
|
||||||
// than what their MaxLength allows them to, cycling sometimes occur,
|
// than what their MaxLength allows them to, cycling sometimes occur,
|
||||||
// but does not fully clears itself: some descriptions are messed up with.
|
// but does not fully clears itself: some descriptions are messed up with.
|
||||||
// We always clear the screen as a result, between writings.
|
// We always clear the screen as a result, between writings.
|
||||||
print(seqClearScreenBelow)
|
//rl.bufprint(seqClearScreenBelow)
|
||||||
|
|
||||||
// Crop the completions so that it fits within our MaxTabCompleterRows
|
// Crop the completions so that it fits within our MaxTabCompleterRows
|
||||||
completions, rl.tcUsedY = rl.cropCompletions(completions)
|
completions, rl.tcUsedY = rl.cropCompletions(completions)
|
||||||
|
|
||||||
// Then we print all of them.
|
// Then we print all of them.
|
||||||
fmt.Printf(completions)
|
rl.bufprintF(completions)
|
||||||
|
rl.bufflush()
|
||||||
}
|
}
|
||||||
|
|
||||||
// cropCompletions - When the user cycles through a completion list longer
|
// cropCompletions - When the user cycles through a completion list longer
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package readline
|
package readline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/text/width"
|
"golang.org/x/text/width"
|
||||||
|
@ -10,7 +11,7 @@ import (
|
||||||
// it should coordinate reprinting the input line, any Infos and completions
|
// it should coordinate reprinting the input line, any Infos and completions
|
||||||
// and manage to get back to the current (computed) cursor coordinates
|
// and manage to get back to the current (computed) cursor coordinates
|
||||||
func (rl *Instance) updateHelpers() {
|
func (rl *Instance) updateHelpers() {
|
||||||
|
print(seqHideCursor)
|
||||||
// Load all Infos & completions before anything.
|
// Load all Infos & completions before anything.
|
||||||
// Thus overwrites anything having been dirtily added/forced/modified, like rl.SetInfoText()
|
// Thus overwrites anything having been dirtily added/forced/modified, like rl.SetInfoText()
|
||||||
rl.getInfoText()
|
rl.getInfoText()
|
||||||
|
@ -27,6 +28,7 @@ func (rl *Instance) updateHelpers() {
|
||||||
// We are at the prompt line (with the latter
|
// We are at the prompt line (with the latter
|
||||||
// not printed yet), then reprint everything
|
// not printed yet), then reprint everything
|
||||||
rl.renderHelpers()
|
rl.renderHelpers()
|
||||||
|
print(seqUnhideCursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabWidth = 4
|
const tabWidth = 4
|
||||||
|
@ -119,7 +121,7 @@ func (rl *Instance) clearHelpers() {
|
||||||
moveCursorForwards(rl.fullX)
|
moveCursorForwards(rl.fullX)
|
||||||
|
|
||||||
// Clear everything below
|
// Clear everything below
|
||||||
print(seqClearScreenBelow)
|
//print(seqClearScreenBelow)
|
||||||
|
|
||||||
// Go back to current cursor position
|
// Go back to current cursor position
|
||||||
moveCursorBackwards(GetTermWidth())
|
moveCursorBackwards(GetTermWidth())
|
||||||
|
@ -194,3 +196,15 @@ func (rl *Instance) renderHelpers() {
|
||||||
moveCursorUp(rl.fullY - rl.posY)
|
moveCursorUp(rl.fullY - rl.posY)
|
||||||
moveCursorForwards(rl.posX)
|
moveCursorForwards(rl.posX)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rl *Instance) bufprintF(format string, a ...any) {
|
||||||
|
fmt.Fprintf(rl.bufferedOut, format, a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rl *Instance) bufprint(text string) {
|
||||||
|
fmt.Fprint(rl.bufferedOut, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rl *Instance) bufflush() {
|
||||||
|
rl.bufferedOut.Flush()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue