mirror of
https://github.com/Hilbis/Hilbish
synced 2025-07-01 16:52:03 +00:00
fix: document functions
This commit is contained in:
parent
96250f8227
commit
2fcbe0ad4c
@ -85,6 +85,7 @@ var prefix = map[string]string{
|
|||||||
"bait": "b",
|
"bait": "b",
|
||||||
"terminal": "term",
|
"terminal": "term",
|
||||||
"snail": "snail",
|
"snail": "snail",
|
||||||
|
"readline": "rl",
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTagsAndDocs(docs string) (map[string][]tag, []string) {
|
func getTagsAndDocs(docs string) (map[string][]tag, []string) {
|
||||||
|
@ -1,124 +0,0 @@
|
|||||||
---
|
|
||||||
title: Module hilbish.editor
|
|
||||||
description: interactions for Hilbish's line reader
|
|
||||||
layout: doc
|
|
||||||
menu:
|
|
||||||
docs:
|
|
||||||
parent: "API"
|
|
||||||
---
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
The hilbish.editor interface provides functions to
|
|
||||||
directly interact with the line editor in use.
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|||
|
|
||||||
|----|----|
|
|
||||||
|<a href="#editor.deleteByAmount">deleteByAmount(amount)</a>|Deletes characters in the line by the given amount.|
|
|
||||||
|<a href="#editor.getLine">getLine() -> string</a>|Returns the current input line.|
|
|
||||||
|<a href="#editor.getVimRegister">getVimRegister(register) -> string</a>|Returns the text that is at the register.|
|
|
||||||
|<a href="#editor.insert">insert(text)</a>|Inserts text into the Hilbish command line.|
|
|
||||||
|<a href="#editor.getChar">getChar() -> string</a>|Reads a keystroke from the user. This is in a format of something like Ctrl-L.|
|
|
||||||
|<a href="#editor.setVimRegister">setVimRegister(register, text)</a>|Sets the vim register at `register` to hold the passed text.|
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<div id='editor.deleteByAmount'>
|
|
||||||
<h4 class='heading'>
|
|
||||||
hilbish.editor.deleteByAmount(amount)
|
|
||||||
<a href="#editor.deleteByAmount" class='heading-link'>
|
|
||||||
<i class="fas fa-paperclip"></i>
|
|
||||||
</a>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
Deletes characters in the line by the given amount.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
`number` **`amount`**
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<div id='editor.getLine'>
|
|
||||||
<h4 class='heading'>
|
|
||||||
hilbish.editor.getLine() -> string
|
|
||||||
<a href="#editor.getLine" class='heading-link'>
|
|
||||||
<i class="fas fa-paperclip"></i>
|
|
||||||
</a>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
Returns the current input line.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
This function has no parameters.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<div id='editor.getVimRegister'>
|
|
||||||
<h4 class='heading'>
|
|
||||||
hilbish.editor.getVimRegister(register) -> string
|
|
||||||
<a href="#editor.getVimRegister" class='heading-link'>
|
|
||||||
<i class="fas fa-paperclip"></i>
|
|
||||||
</a>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
Returns the text that is at the register.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
`string` **`register`**
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<div id='editor.insert'>
|
|
||||||
<h4 class='heading'>
|
|
||||||
hilbish.editor.insert(text)
|
|
||||||
<a href="#editor.insert" class='heading-link'>
|
|
||||||
<i class="fas fa-paperclip"></i>
|
|
||||||
</a>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
Inserts text into the Hilbish command line.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
`string` **`text`**
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<div id='editor.getChar'>
|
|
||||||
<h4 class='heading'>
|
|
||||||
hilbish.editor.getChar() -> string
|
|
||||||
<a href="#editor.getChar" class='heading-link'>
|
|
||||||
<i class="fas fa-paperclip"></i>
|
|
||||||
</a>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
Reads a keystroke from the user. This is in a format of something like Ctrl-L.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
This function has no parameters.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<div id='editor.setVimRegister'>
|
|
||||||
<h4 class='heading'>
|
|
||||||
hilbish.editor.setVimRegister(register, text)
|
|
||||||
<a href="#editor.setVimRegister" class='heading-link'>
|
|
||||||
<i class="fas fa-paperclip"></i>
|
|
||||||
</a>
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
Sets the vim register at `register` to hold the passed text.
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
`string` **`register`**
|
|
||||||
|
|
||||||
|
|
||||||
`string` **`text`**
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Module readline
|
title: Module readline
|
||||||
description: Package readline is a pure-Go re-imagining of the UNIX readline API
|
description: line reader library
|
||||||
layout: doc
|
layout: doc
|
||||||
menu:
|
menu:
|
||||||
docs:
|
docs:
|
||||||
@ -8,38 +8,60 @@ menu:
|
|||||||
---
|
---
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
This package is designed to be run independently from murex and at some
|
|
||||||
point it will be separated into it's own git repository (at a stage when I
|
|
||||||
am confident that murex will no longer be the primary driver for features,
|
|
||||||
bugs or other code changes)
|
|
||||||
|
|
||||||
line reader library
|
|
||||||
The readline module is responsible for reading input from the user.
|
The readline module is responsible for reading input from the user.
|
||||||
The readline module is what Hilbish uses to read input from the user,
|
The readline module is what Hilbish uses to read input from the user,
|
||||||
including all the interactive features of Hilbish like history search,
|
including all the interactive features of Hilbish like history search,
|
||||||
syntax highlighting, everything. The global Hilbish readline instance
|
syntax highlighting, everything. The global Hilbish readline instance
|
||||||
is usable at `hilbish.editor`.
|
is usable at `hilbish.editor`.
|
||||||
|
|
||||||
Package terminal provides support functions for dealing with terminals, as
|
## Functions
|
||||||
commonly found on UNIX systems.
|
|||
|
||||||
|
|----|----|
|
||||||
|
|<a href="#New">new() -> @Readline</a>|Creates a new readline instance.|
|
||||||
|
|
||||||
Putting a terminal into raw mode is the most common requirement:
|
<hr>
|
||||||
|
<div id='New'>
|
||||||
|
<h4 class='heading'>
|
||||||
|
readline.new() -> <a href="/Hilbish/docs/api/readline/#readline" style="text-decoration: none;" id="lol">Readline</a>
|
||||||
|
<a href="#New" class='heading-link'>
|
||||||
|
<i class="fas fa-paperclip"></i>
|
||||||
|
</a>
|
||||||
|
</h4>
|
||||||
|
|
||||||
oldState, err := terminal.MakeRaw(0)
|
Creates a new readline instance.
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer terminal.Restore(0, oldState)
|
|
||||||
|
|
||||||
Package terminal provides support functions for dealing with terminals, as
|
#### Parameters
|
||||||
commonly found on UNIX systems.
|
This function has no parameters.
|
||||||
|
</div>
|
||||||
|
|
||||||
Putting a terminal into raw mode is the most common requirement:
|
## Types
|
||||||
|
<hr>
|
||||||
|
|
||||||
oldState, err := terminal.MakeRaw(0)
|
## Readline
|
||||||
if err != nil {
|
blah blah
|
||||||
panic(err)
|
|
||||||
}
|
### Methods
|
||||||
defer terminal.Restore(0, oldState)
|
#### deleteByAmount(amount)
|
||||||
|
Deletes characters in the line by the given amount.
|
||||||
|
|
||||||
|
#### getLine() -> string
|
||||||
|
Returns the current input line.
|
||||||
|
|
||||||
|
#### getVimRegister(register) -> string
|
||||||
|
Returns the text that is at the register.
|
||||||
|
|
||||||
|
#### insert(text)
|
||||||
|
Inserts text into the Hilbish command line.
|
||||||
|
|
||||||
|
#### log(text)
|
||||||
|
Prints a message *before* the prompt without it being interrupted by user input.
|
||||||
|
|
||||||
|
#### read() -> string
|
||||||
|
Reads input from the user.
|
||||||
|
|
||||||
|
#### getChar() -> string
|
||||||
|
Reads a keystroke from the user. This is in a format of something like Ctrl-L.
|
||||||
|
|
||||||
|
#### setVimRegister(register, text)
|
||||||
|
Sets the vim register at `register` to hold the passed text.
|
||||||
|
|
||||||
|
128
editor.go
128
editor.go
@ -1,128 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"hilbish/util"
|
|
||||||
|
|
||||||
rt "github.com/arnodel/golua/runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
// #interface editor
|
|
||||||
// interactions for Hilbish's line reader
|
|
||||||
// The hilbish.editor interface provides functions to
|
|
||||||
// directly interact with the line editor in use.
|
|
||||||
func editorLoader(rtm *rt.Runtime) *rt.Table {
|
|
||||||
exports := map[string]util.LuaExport{
|
|
||||||
"insert": {editorInsert, 1, false},
|
|
||||||
"setVimRegister": {editorSetRegister, 1, false},
|
|
||||||
"getVimRegister": {editorGetRegister, 2, false},
|
|
||||||
"getLine": {editorGetLine, 0, false},
|
|
||||||
"readChar": {editorReadChar, 0, false},
|
|
||||||
"deleteByAmount": {editorDeleteByAmount, 1, false},
|
|
||||||
}
|
|
||||||
|
|
||||||
mod := rt.NewTable()
|
|
||||||
util.SetExports(rtm, mod, exports)
|
|
||||||
|
|
||||||
return mod
|
|
||||||
}
|
|
||||||
|
|
||||||
// #interface editor
|
|
||||||
// insert(text)
|
|
||||||
// Inserts text into the Hilbish command line.
|
|
||||||
// #param text string
|
|
||||||
func editorInsert(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|
||||||
if err := c.Check1Arg(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
text, err := c.StringArg(0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
lr.rl.Insert(text)
|
|
||||||
|
|
||||||
return c.Next(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// #interface editor
|
|
||||||
// setVimRegister(register, text)
|
|
||||||
// Sets the vim register at `register` to hold the passed text.
|
|
||||||
// #param register string
|
|
||||||
// #param text string
|
|
||||||
func editorSetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|
||||||
if err := c.Check1Arg(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
register, err := c.StringArg(0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
text, err := c.StringArg(1)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
lr.rl.SetRegisterBuf(register, []rune(text))
|
|
||||||
|
|
||||||
return c.Next(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// #interface editor
|
|
||||||
// getVimRegister(register) -> string
|
|
||||||
// Returns the text that is at the register.
|
|
||||||
// #param register string
|
|
||||||
func editorGetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|
||||||
if err := c.Check1Arg(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
register, err := c.StringArg(0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := lr.rl.GetFromRegister(register)
|
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// #interface editor
|
|
||||||
// getLine() -> string
|
|
||||||
// Returns the current input line.
|
|
||||||
// #returns string
|
|
||||||
func editorGetLine(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|
||||||
buf := lr.rl.GetLine()
|
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// #interface editor
|
|
||||||
// getChar() -> string
|
|
||||||
// Reads a keystroke from the user. This is in a format of something like Ctrl-L.
|
|
||||||
func editorReadChar(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|
||||||
buf := lr.rl.ReadChar()
|
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// #interface editor
|
|
||||||
// deleteByAmount(amount)
|
|
||||||
// Deletes characters in the line by the given amount.
|
|
||||||
// #param amount number
|
|
||||||
func editorDeleteByAmount(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|
||||||
if err := c.Check1Arg(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
amount, err := c.IntArg(0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
lr.rl.DeleteByAmount(int(amount))
|
|
||||||
|
|
||||||
return c.Next(), nil
|
|
||||||
}
|
|
@ -7,24 +7,6 @@ local hilbish = {}
|
|||||||
--- @param cmd string
|
--- @param cmd string
|
||||||
function hilbish.aliases.add(alias, cmd) end
|
function hilbish.aliases.add(alias, cmd) end
|
||||||
|
|
||||||
--- Deletes characters in the line by the given amount.
|
|
||||||
function hilbish.editor.deleteByAmount(amount) end
|
|
||||||
|
|
||||||
--- Returns the current input line.
|
|
||||||
function hilbish.editor.getLine() end
|
|
||||||
|
|
||||||
--- Returns the text that is at the register.
|
|
||||||
function hilbish.editor.getVimRegister(register) end
|
|
||||||
|
|
||||||
--- Inserts text into the Hilbish command line.
|
|
||||||
function hilbish.editor.insert(text) end
|
|
||||||
|
|
||||||
--- Reads a keystroke from the user. This is in a format of something like Ctrl-L.
|
|
||||||
function hilbish.editor.getChar() end
|
|
||||||
|
|
||||||
--- Sets the vim register at `register` to hold the passed text.
|
|
||||||
function hilbish.editor.setVimRegister(register, text) end
|
|
||||||
|
|
||||||
--- Return binaries/executables based on the provided parameters.
|
--- Return binaries/executables based on the provided parameters.
|
||||||
--- This function is meant to be used as a helper in a command completion handler.
|
--- This function is meant to be used as a helper in a command completion handler.
|
||||||
---
|
---
|
||||||
|
@ -2,4 +2,31 @@
|
|||||||
|
|
||||||
local readline = {}
|
local readline = {}
|
||||||
|
|
||||||
|
--- Deletes characters in the line by the given amount.
|
||||||
|
function readline:deleteByAmount(amount) end
|
||||||
|
|
||||||
|
--- Returns the current input line.
|
||||||
|
function readline:getLine() end
|
||||||
|
|
||||||
|
--- Returns the text that is at the register.
|
||||||
|
function readline:getVimRegister(register) end
|
||||||
|
|
||||||
|
--- Inserts text into the Hilbish command line.
|
||||||
|
function readline:insert(text) end
|
||||||
|
|
||||||
|
--- Prints a message *before* the prompt without it being interrupted by user input.
|
||||||
|
function readline:log(text) end
|
||||||
|
|
||||||
|
--- Creates a new readline instance.
|
||||||
|
function readline.new() end
|
||||||
|
|
||||||
|
--- Reads input from the user.
|
||||||
|
function readline:read() end
|
||||||
|
|
||||||
|
--- Reads a keystroke from the user. This is in a format of something like Ctrl-L.
|
||||||
|
function readline:getChar() end
|
||||||
|
|
||||||
|
--- Sets the vim register at `register` to hold the passed text.
|
||||||
|
function readline:setVimRegister(register, text) end
|
||||||
|
|
||||||
return readline
|
return readline
|
||||||
|
@ -143,54 +143,93 @@ const (
|
|||||||
|
|
||||||
// TODO: return whether its actually a sequence or not
|
// TODO: return whether its actually a sequence or not
|
||||||
// remedies the edge case of someone literally typing Ctrl-A for example.
|
// remedies the edge case of someone literally typing Ctrl-A for example.
|
||||||
func (rl *Instance) ReadChar() string {
|
func (rl *Readline) ReadChar() string {
|
||||||
b := make([]byte, 1024)
|
b := make([]byte, 1024)
|
||||||
i, _ := os.Stdin.Read(b)
|
i, _ := os.Stdin.Read(b)
|
||||||
r := []rune(string(b))
|
r := []rune(string(b))
|
||||||
s := string(r[:i])
|
s := string(r[:i])
|
||||||
|
|
||||||
switch b[0] {
|
switch b[0] {
|
||||||
case charCtrlA: return "Ctrl-A"
|
case charCtrlA:
|
||||||
case charCtrlB: return "Ctrl-B"
|
return "Ctrl-A"
|
||||||
case charCtrlC: return "Ctrl-C"
|
case charCtrlB:
|
||||||
case charEOF: return "Ctrl-D"
|
return "Ctrl-B"
|
||||||
case charCtrlE: return "Ctrl-E"
|
case charCtrlC:
|
||||||
case charCtrlF: return "Ctrl-F"
|
return "Ctrl-C"
|
||||||
case charCtrlG: return "Ctrl-G"
|
case charEOF:
|
||||||
case charBackspace, charBackspace2: return "Backspace"
|
return "Ctrl-D"
|
||||||
case charTab: return "Tab"
|
case charCtrlE:
|
||||||
case charCtrlK: return "Ctrl-K"
|
return "Ctrl-E"
|
||||||
case charCtrlL: return "Ctrl-L"
|
case charCtrlF:
|
||||||
case charCtrlN: return "Ctrl-N"
|
return "Ctrl-F"
|
||||||
case charCtrlO: return "Ctrl-O"
|
case charCtrlG:
|
||||||
case charCtrlP: return "Ctrl-P"
|
return "Ctrl-G"
|
||||||
case charCtrlQ: return "Ctrl-Q"
|
case charBackspace, charBackspace2:
|
||||||
case charCtrlR: return "Ctrl-R"
|
return "Backspace"
|
||||||
case charCtrlS: return "Ctrl-S"
|
case charTab:
|
||||||
case charCtrlT: return "Ctrl-T"
|
return "Tab"
|
||||||
case charCtrlU: return "Ctrl-U"
|
case charCtrlK:
|
||||||
case charCtrlV: return "Ctrl-V"
|
return "Ctrl-K"
|
||||||
case charCtrlW: return "Ctrl-W"
|
case charCtrlL:
|
||||||
case charCtrlX: return "Ctrl-X"
|
return "Ctrl-L"
|
||||||
case charCtrlY: return "Ctrl-Y"
|
case charCtrlN:
|
||||||
case charCtrlZ: return "Ctrl-Z"
|
return "Ctrl-N"
|
||||||
case '\r': fallthrough
|
case charCtrlO:
|
||||||
case '\n': return "Enter"
|
return "Ctrl-O"
|
||||||
|
case charCtrlP:
|
||||||
|
return "Ctrl-P"
|
||||||
|
case charCtrlQ:
|
||||||
|
return "Ctrl-Q"
|
||||||
|
case charCtrlR:
|
||||||
|
return "Ctrl-R"
|
||||||
|
case charCtrlS:
|
||||||
|
return "Ctrl-S"
|
||||||
|
case charCtrlT:
|
||||||
|
return "Ctrl-T"
|
||||||
|
case charCtrlU:
|
||||||
|
return "Ctrl-U"
|
||||||
|
case charCtrlV:
|
||||||
|
return "Ctrl-V"
|
||||||
|
case charCtrlW:
|
||||||
|
return "Ctrl-W"
|
||||||
|
case charCtrlX:
|
||||||
|
return "Ctrl-X"
|
||||||
|
case charCtrlY:
|
||||||
|
return "Ctrl-Y"
|
||||||
|
case charCtrlZ:
|
||||||
|
return "Ctrl-Z"
|
||||||
|
case '\r':
|
||||||
|
fallthrough
|
||||||
|
case '\n':
|
||||||
|
return "Enter"
|
||||||
case charEscape:
|
case charEscape:
|
||||||
switch s {
|
switch s {
|
||||||
case string(charEscape): return "Escape"
|
case string(charEscape):
|
||||||
case seqUp: return "Up"
|
return "Escape"
|
||||||
case seqDown: return "Down"
|
case seqUp:
|
||||||
case seqBackwards: return "Left"
|
return "Up"
|
||||||
case seqForwards: return "Right"
|
case seqDown:
|
||||||
case seqCtrlLeftArrow: return "Ctrl-Left"
|
return "Down"
|
||||||
case seqCtrlRightArrow: return "Ctrl-Right"
|
case seqBackwards:
|
||||||
case seqCtrlDelete, seqCtrlDelete2: return "Ctrl-Delete"
|
return "Left"
|
||||||
case seqHome, seqHomeSc: return "Home"
|
case seqForwards:
|
||||||
case seqEnd, seqEndSc: return "End"
|
return "Right"
|
||||||
case seqDelete, seqDelete2: return "Delete"
|
case seqCtrlLeftArrow:
|
||||||
case seqPageUp: return "Page-Up"
|
return "Ctrl-Left"
|
||||||
case seqPageDown: return "Page-Down"
|
case seqCtrlRightArrow:
|
||||||
|
return "Ctrl-Right"
|
||||||
|
case seqCtrlDelete, seqCtrlDelete2:
|
||||||
|
return "Ctrl-Delete"
|
||||||
|
case seqHome, seqHomeSc:
|
||||||
|
return "Home"
|
||||||
|
case seqEnd, seqEndSc:
|
||||||
|
return "End"
|
||||||
|
case seqDelete, seqDelete2:
|
||||||
|
return "Delete"
|
||||||
|
case seqPageUp:
|
||||||
|
return "Page-Up"
|
||||||
|
case seqPageDown:
|
||||||
|
return "Page-Down"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/rivo/uniseg"
|
"github.com/rivo/uniseg"
|
||||||
)
|
)
|
||||||
|
|
||||||
// initGrid - Grid display details. Called each time we want to be sure to have
|
// initGrid - Grid display details. Called each time we want to be sure to have
|
||||||
// a working completion group either immediately, or later on. Generally defered.
|
// a working completion group either immediately, or later on. Generally defered.
|
||||||
func (g *CompletionGroup) initGrid(rl *Instance) {
|
func (g *CompletionGroup) initGrid(rl *Readline) {
|
||||||
|
|
||||||
// Compute size of each completion item box
|
// Compute size of each completion item box
|
||||||
tcMaxLength := 1
|
tcMaxLength := 1
|
||||||
@ -44,7 +45,7 @@ func (g *CompletionGroup) initGrid(rl *Instance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// moveTabGridHighlight - Moves the highlighting for currently selected completion item (grid display)
|
// moveTabGridHighlight - Moves the highlighting for currently selected completion item (grid display)
|
||||||
func (g *CompletionGroup) moveTabGridHighlight(rl *Instance, x, y int) (done bool, next bool) {
|
func (g *CompletionGroup) moveTabGridHighlight(rl *Readline, x, y int) (done bool, next bool) {
|
||||||
|
|
||||||
g.tcPosX += x
|
g.tcPosX += x
|
||||||
g.tcPosY += y
|
g.tcPosY += y
|
||||||
@ -96,7 +97,7 @@ func (g *CompletionGroup) moveTabGridHighlight(rl *Instance, x, y int) (done boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeGrid - A grid completion string
|
// writeGrid - A grid completion string
|
||||||
func (g *CompletionGroup) writeGrid(rl *Instance) (comp string) {
|
func (g *CompletionGroup) writeGrid(rl *Readline) (comp string) {
|
||||||
|
|
||||||
// If group title, print it and adjust offset.
|
// If group title, print it and adjust offset.
|
||||||
if g.Name != "" {
|
if g.Name != "" {
|
||||||
@ -127,9 +128,9 @@ func (g *CompletionGroup) writeGrid(rl *Instance) (comp string) {
|
|||||||
|
|
||||||
sugg := g.Suggestions[i]
|
sugg := g.Suggestions[i]
|
||||||
if len(sugg) > GetTermWidth() {
|
if len(sugg) > GetTermWidth() {
|
||||||
sugg = sugg[:GetTermWidth() - 4] + "..."
|
sugg = sugg[:GetTermWidth()-4] + "..."
|
||||||
}
|
}
|
||||||
formatStr := "%-"+cellWidth+"s%s "
|
formatStr := "%-" + cellWidth + "s%s "
|
||||||
if g.tcMaxX == 1 {
|
if g.tcMaxX == 1 {
|
||||||
formatStr = "%s%s"
|
formatStr = "%s%s"
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ type CompletionGroup struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// init - The completion group computes and sets all its values, and is then ready to work.
|
// init - The completion group computes and sets all its values, and is then ready to work.
|
||||||
func (g *CompletionGroup) init(rl *Instance) {
|
func (g *CompletionGroup) init(rl *Readline) {
|
||||||
|
|
||||||
// Details common to all displays
|
// Details common to all displays
|
||||||
g.checkCycle(rl) // Based on the number of groups given to the shell, allows cycling or not
|
g.checkCycle(rl) // Based on the number of groups given to the shell, allows cycling or not
|
||||||
@ -70,7 +70,7 @@ func (g *CompletionGroup) init(rl *Instance) {
|
|||||||
// updateTabFind - When searching through all completion groups (whether it be command history or not),
|
// updateTabFind - When searching through all completion groups (whether it be command history or not),
|
||||||
// we ask each of them to filter its own items and return the results to the shell for aggregating them.
|
// we ask each of them to filter its own items and return the results to the shell for aggregating them.
|
||||||
// The rx parameter is passed, as the shell already checked that the search pattern is valid.
|
// The rx parameter is passed, as the shell already checked that the search pattern is valid.
|
||||||
func (g *CompletionGroup) updateTabFind(rl *Instance) {
|
func (g *CompletionGroup) updateTabFind(rl *Readline) {
|
||||||
|
|
||||||
suggs := rl.Searcher(rl.search, g.Suggestions)
|
suggs := rl.Searcher(rl.search, g.Suggestions)
|
||||||
// We perform filter right here, so we create a new completion group, and populate it with our results.
|
// We perform filter right here, so we create a new completion group, and populate it with our results.
|
||||||
@ -97,7 +97,7 @@ func (g *CompletionGroup) updateTabFind(rl *Instance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// checkCycle - Based on the number of groups given to the shell, allows cycling or not
|
// checkCycle - Based on the number of groups given to the shell, allows cycling or not
|
||||||
func (g *CompletionGroup) checkCycle(rl *Instance) {
|
func (g *CompletionGroup) checkCycle(rl *Readline) {
|
||||||
if len(rl.tcGroups) == 1 {
|
if len(rl.tcGroups) == 1 {
|
||||||
g.allowCycle = true
|
g.allowCycle = true
|
||||||
}
|
}
|
||||||
@ -108,7 +108,7 @@ func (g *CompletionGroup) checkCycle(rl *Instance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// checkMaxLength - Based on the number of groups given to the shell, check/set MaxLength defaults
|
// checkMaxLength - Based on the number of groups given to the shell, check/set MaxLength defaults
|
||||||
func (g *CompletionGroup) checkMaxLength(rl *Instance) {
|
func (g *CompletionGroup) checkMaxLength(rl *Readline) {
|
||||||
|
|
||||||
// This means the user forgot to set it
|
// This means the user forgot to set it
|
||||||
if g.MaxLength == 0 {
|
if g.MaxLength == 0 {
|
||||||
@ -147,7 +147,7 @@ func checkNilItems(groups []*CompletionGroup) (checked []*CompletionGroup) {
|
|||||||
|
|
||||||
// writeCompletion - This function produces a formatted string containing all appropriate items
|
// writeCompletion - This function produces a formatted string containing all appropriate items
|
||||||
// and according to display settings. This string is then appended to the main completion string.
|
// and according to display settings. This string is then appended to the main completion string.
|
||||||
func (g *CompletionGroup) writeCompletion(rl *Instance) (comp string) {
|
func (g *CompletionGroup) writeCompletion(rl *Readline) (comp string) {
|
||||||
|
|
||||||
// Avoids empty groups in suggestions
|
// Avoids empty groups in suggestions
|
||||||
if len(g.Suggestions) == 0 {
|
if len(g.Suggestions) == 0 {
|
||||||
@ -169,7 +169,7 @@ func (g *CompletionGroup) writeCompletion(rl *Instance) (comp string) {
|
|||||||
|
|
||||||
// getCurrentCell - The completion groups computes the current cell value,
|
// getCurrentCell - The completion groups computes the current cell value,
|
||||||
// depending on its display type and its different parameters
|
// depending on its display type and its different parameters
|
||||||
func (g *CompletionGroup) getCurrentCell(rl *Instance) string {
|
func (g *CompletionGroup) getCurrentCell(rl *Readline) string {
|
||||||
|
|
||||||
switch g.DisplayType {
|
switch g.DisplayType {
|
||||||
case TabDisplayGrid:
|
case TabDisplayGrid:
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
// initList - List display details. Because of the way alternative completions
|
// initList - List display details. Because of the way alternative completions
|
||||||
// are handled, MaxLength cannot be set when there are alternative completions.
|
// are handled, MaxLength cannot be set when there are alternative completions.
|
||||||
func (g *CompletionGroup) initList(rl *Instance) {
|
func (g *CompletionGroup) initList(rl *Readline) {
|
||||||
|
|
||||||
// We may only ever have two different
|
// We may only ever have two different
|
||||||
// columns: (suggestions, and alternatives)
|
// columns: (suggestions, and alternatives)
|
||||||
@ -53,7 +53,7 @@ func (g *CompletionGroup) initList(rl *Instance) {
|
|||||||
|
|
||||||
// moveTabListHighlight - Moves the highlighting for currently selected completion item (list display)
|
// moveTabListHighlight - Moves the highlighting for currently selected completion item (list display)
|
||||||
// We don't care about the x, because only can have 2 columns of selectable choices (--long and -s)
|
// We don't care about the x, because only can have 2 columns of selectable choices (--long and -s)
|
||||||
func (g *CompletionGroup) moveTabListHighlight(rl *Instance, x, y int) (done bool, next bool) {
|
func (g *CompletionGroup) moveTabListHighlight(rl *Readline, x, y int) (done bool, next bool) {
|
||||||
|
|
||||||
// We dont' pass to x, because not managed by callers
|
// We dont' pass to x, because not managed by callers
|
||||||
g.tcPosY += x
|
g.tcPosY += x
|
||||||
@ -153,7 +153,7 @@ func (g *CompletionGroup) moveTabListHighlight(rl *Instance, x, y int) (done boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeList - A list completion string
|
// writeList - A list completion string
|
||||||
func (g *CompletionGroup) writeList(rl *Instance) (comp string) {
|
func (g *CompletionGroup) writeList(rl *Readline) (comp string) {
|
||||||
|
|
||||||
// Print group title and adjust offset if there is one.
|
// Print group title and adjust offset if there is one.
|
||||||
if g.Name != "" {
|
if g.Name != "" {
|
||||||
@ -249,7 +249,7 @@ func (g *CompletionGroup) writeList(rl *Instance) (comp string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) getListPad() (pad int) {
|
func (rl *Readline) getListPad() (pad int) {
|
||||||
for _, group := range rl.tcGroups {
|
for _, group := range rl.tcGroups {
|
||||||
if group.DisplayType == TabDisplayList {
|
if group.DisplayType == TabDisplayList {
|
||||||
for i := range group.Suggestions {
|
for i := range group.Suggestions {
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
// initMap - Map display details. Called each time we want to be sure to have
|
// initMap - Map display details. Called each time we want to be sure to have
|
||||||
// a working completion group either immediately, or later on. Generally defered.
|
// a working completion group either immediately, or later on. Generally defered.
|
||||||
func (g *CompletionGroup) initMap(rl *Instance) {
|
func (g *CompletionGroup) initMap(rl *Readline) {
|
||||||
|
|
||||||
// We make the map anyway, especially if we need to use it later
|
// We make the map anyway, especially if we need to use it later
|
||||||
if g.Descriptions == nil {
|
if g.Descriptions == nil {
|
||||||
@ -35,7 +35,7 @@ func (g *CompletionGroup) initMap(rl *Instance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// moveTabMapHighlight - Moves the highlighting for currently selected completion item (map display)
|
// moveTabMapHighlight - Moves the highlighting for currently selected completion item (map display)
|
||||||
func (g *CompletionGroup) moveTabMapHighlight(rl *Instance, x, y int) (done bool, next bool) {
|
func (g *CompletionGroup) moveTabMapHighlight(rl *Readline, x, y int) (done bool, next bool) {
|
||||||
|
|
||||||
g.tcPosY += x
|
g.tcPosY += x
|
||||||
g.tcPosY += y
|
g.tcPosY += y
|
||||||
@ -72,7 +72,7 @@ func (g *CompletionGroup) moveTabMapHighlight(rl *Instance, x, y int) (done bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeMap - A map or list completion string
|
// writeMap - A map or list completion string
|
||||||
func (g *CompletionGroup) writeMap(rl *Instance) (comp string) {
|
func (g *CompletionGroup) writeMap(rl *Readline) (comp string) {
|
||||||
|
|
||||||
if g.Name != "" {
|
if g.Name != "" {
|
||||||
// Print group title (changes with line returns depending on type)
|
// Print group title (changes with line returns depending on type)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package readline
|
package readline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// "fmt"
|
// "fmt"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -28,7 +28,7 @@ func leftMost() []byte {
|
|||||||
|
|
||||||
var rxRcvCursorPos = regexp.MustCompile("^\x1b([0-9]+);([0-9]+)R$")
|
var rxRcvCursorPos = regexp.MustCompile("^\x1b([0-9]+);([0-9]+)R$")
|
||||||
|
|
||||||
func (rl *Instance) getCursorPos() (x int, y int) {
|
func (rl *Readline) getCursorPos() (x int, y int) {
|
||||||
if !rl.EnableGetCursorPos {
|
if !rl.EnableGetCursorPos {
|
||||||
return -1, -1
|
return -1, -1
|
||||||
}
|
}
|
||||||
@ -143,7 +143,7 @@ func unhideCursor() {
|
|||||||
print(seqUnhideCursor)
|
print(seqUnhideCursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) backspace(forward bool) {
|
func (rl *Readline) backspace(forward bool) {
|
||||||
if len(rl.line) == 0 || rl.pos == 0 {
|
if len(rl.line) == 0 || rl.pos == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -151,7 +151,7 @@ func (rl *Instance) backspace(forward bool) {
|
|||||||
rl.deleteBackspace(forward)
|
rl.deleteBackspace(forward)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) moveCursorByAdjust(adjust int) {
|
func (rl *Readline) moveCursorByAdjust(adjust int) {
|
||||||
switch {
|
switch {
|
||||||
case adjust > 0:
|
case adjust > 0:
|
||||||
rl.pos += adjust
|
rl.pos += adjust
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// writeTempFile - This function optionally accepts a filename (generally specified with an extension).
|
// writeTempFile - This function optionally accepts a filename (generally specified with an extension).
|
||||||
func (rl *Instance) writeTempFile(content []byte, filename string) (string, error) {
|
func (rl *Readline) writeTempFile(content []byte, filename string) (string, error) {
|
||||||
// The final path to the buffer on disk
|
// The final path to the buffer on disk
|
||||||
var path string
|
var path string
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ const defaultEditor = "vi"
|
|||||||
// depending on the actions taken by the user within it (eg: x or q! in Vim)
|
// depending on the actions taken by the user within it (eg: x or q! in Vim)
|
||||||
// The filename parameter can be used to pass a specific filename.ext pattern,
|
// The filename parameter can be used to pass a specific filename.ext pattern,
|
||||||
// which might be useful if the editor has builtin filetype plugin functionality.
|
// which might be useful if the editor has builtin filetype plugin functionality.
|
||||||
func (rl *Instance) StartEditorWithBuffer(multiline []rune, filename string) ([]rune, error) {
|
func (rl *Readline) StartEditorWithBuffer(multiline []rune, filename string) ([]rune, error) {
|
||||||
name, err := rl.writeTempFile([]byte(string(multiline)), filename)
|
name, err := rl.writeTempFile([]byte(string(multiline)), filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return multiline, err
|
return multiline, err
|
||||||
|
@ -13,11 +13,11 @@ type EventReturn struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddEvent registers a new keypress handler
|
// AddEvent registers a new keypress handler
|
||||||
func (rl *Instance) AddEvent(keyPress string, callback func(string, []rune, int) *EventReturn) {
|
func (rl *Readline) AddEvent(keyPress string, callback func(string, []rune, int) *EventReturn) {
|
||||||
rl.evtKeyPress[keyPress] = callback
|
rl.evtKeyPress[keyPress] = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
// DelEvent deregisters an existing keypress handler
|
// DelEvent deregisters an existing keypress handler
|
||||||
func (rl *Instance) DelEvent(keyPress string) {
|
func (rl *Readline) DelEvent(keyPress string) {
|
||||||
delete(rl.evtKeyPress, keyPress)
|
delete(rl.evtKeyPress, keyPress)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
// Package readline is a pure-Go re-imagining of the UNIX readline API
|
|
||||||
//
|
|
||||||
// This package is designed to be run independently from murex and at some
|
|
||||||
// point it will be separated into it's own git repository (at a stage when I
|
|
||||||
// am confident that murex will no longer be the primary driver for features,
|
|
||||||
// bugs or other code changes)
|
|
||||||
package readline
|
|
@ -11,7 +11,7 @@ func (rl *Instance) SetHintText(s string) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func (rl *Instance) getHintText() {
|
func (rl *Readline) getHintText() {
|
||||||
|
|
||||||
if !rl.modeAutoFind && !rl.modeTabFind {
|
if !rl.modeAutoFind && !rl.modeTabFind {
|
||||||
// Return if no hints provided by the user/engine
|
// Return if no hints provided by the user/engine
|
||||||
@ -27,7 +27,7 @@ func (rl *Instance) getHintText() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeHintText - only writes the hint text and computes its offsets.
|
// writeHintText - only writes the hint text and computes its offsets.
|
||||||
func (rl *Instance) writeHintText() {
|
func (rl *Readline) writeHintText() {
|
||||||
if len(rl.hintText) == 0 {
|
if len(rl.hintText) == 0 {
|
||||||
//rl.hintY = 0
|
//rl.hintY = 0
|
||||||
return
|
return
|
||||||
@ -43,7 +43,7 @@ func (rl *Instance) writeHintText() {
|
|||||||
|
|
||||||
wrapped, hintLen := WrapText(string(rl.hintText), width)
|
wrapped, hintLen := WrapText(string(rl.hintText), width)
|
||||||
offset += hintLen
|
offset += hintLen
|
||||||
// rl.hintY = offset
|
// rl.hintY = offset
|
||||||
|
|
||||||
hintText := string(wrapped)
|
hintText := string(wrapped)
|
||||||
|
|
||||||
@ -52,12 +52,12 @@ func (rl *Instance) writeHintText() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) resetHintText() {
|
func (rl *Readline) resetHintText() {
|
||||||
//rl.hintY = 0
|
//rl.hintY = 0
|
||||||
rl.hintText = []rune{}
|
rl.hintText = []rune{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) insertHintText() {
|
func (rl *Readline) insertHintText() {
|
||||||
if len(rl.hintText) != 0 {
|
if len(rl.hintText) != 0 {
|
||||||
// fill in hint text
|
// fill in hint text
|
||||||
rl.insert(rl.hintText)
|
rl.insert(rl.hintText)
|
||||||
|
@ -29,24 +29,24 @@ type History interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetHistoryCtrlR - Set the history source triggered with Ctrl-r combination
|
// SetHistoryCtrlR - Set the history source triggered with Ctrl-r combination
|
||||||
func (rl *Instance) SetHistoryCtrlR(name string, history History) {
|
func (rl *Readline) SetHistoryCtrlR(name string, history History) {
|
||||||
rl.mainHistName = name
|
rl.mainHistName = name
|
||||||
rl.mainHistory = history
|
rl.mainHistory = history
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHistoryCtrlR - Returns the history source triggered by Ctrl-r
|
// GetHistoryCtrlR - Returns the history source triggered by Ctrl-r
|
||||||
func (rl *Instance) GetHistoryCtrlR() History {
|
func (rl *Readline) GetHistoryCtrlR() History {
|
||||||
return rl.mainHistory
|
return rl.mainHistory
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHistoryAltR - Set the history source triggered with Alt-r combination
|
// SetHistoryAltR - Set the history source triggered with Alt-r combination
|
||||||
func (rl *Instance) SetHistoryAltR(name string, history History) {
|
func (rl *Readline) SetHistoryAltR(name string, history History) {
|
||||||
rl.altHistName = name
|
rl.altHistName = name
|
||||||
rl.altHistory = history
|
rl.altHistory = history
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHistoryAltR - Returns the history source triggered by Alt-r
|
// GetHistoryAltR - Returns the history source triggered by Alt-r
|
||||||
func (rl *Instance) GetHistoryAltR() History {
|
func (rl *Readline) GetHistoryAltR() History {
|
||||||
return rl.altHistory
|
return rl.altHistory
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ func (h *NullHistory) Dump() interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Browse historic lines:
|
// Browse historic lines:
|
||||||
func (rl *Instance) walkHistory(i int) {
|
func (rl *Readline) walkHistory(i int) {
|
||||||
var (
|
var (
|
||||||
old, new string
|
old, new string
|
||||||
dedup bool
|
dedup bool
|
||||||
@ -123,7 +123,7 @@ func (rl *Instance) walkHistory(i int) {
|
|||||||
|
|
||||||
// When we are exiting the current line buffer to move around
|
// When we are exiting the current line buffer to move around
|
||||||
// the history, we make buffer the current line
|
// the history, we make buffer the current line
|
||||||
if rl.histOffset == 0 && rl.histOffset + i == 1 {
|
if rl.histOffset == 0 && rl.histOffset+i == 1 {
|
||||||
rl.lineBuf = string(rl.line)
|
rl.lineBuf = string(rl.line)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +168,7 @@ func (rl *Instance) walkHistory(i int) {
|
|||||||
|
|
||||||
// completeHistory - Populates a CompletionGroup with history and returns it the shell
|
// completeHistory - Populates a CompletionGroup with history and returns it the shell
|
||||||
// we populate only one group, so as to pass it to the main completion engine.
|
// we populate only one group, so as to pass it to the main completion engine.
|
||||||
func (rl *Instance) completeHistory() (hist []*CompletionGroup) {
|
func (rl *Readline) completeHistory() (hist []*CompletionGroup) {
|
||||||
|
|
||||||
hist = make([]*CompletionGroup, 1)
|
hist = make([]*CompletionGroup, 1)
|
||||||
hist[0] = &CompletionGroup{
|
hist[0] = &CompletionGroup{
|
||||||
|
@ -4,12 +4,12 @@ import "regexp"
|
|||||||
|
|
||||||
// SetInfoText - a nasty function to force writing a new info text. It does not update helpers, it just renders
|
// SetInfoText - a nasty function to force writing a new info text. It does not update helpers, it just renders
|
||||||
// them, so the info will survive until the helpers (thus including the info) will be updated/recomputed.
|
// them, so the info will survive until the helpers (thus including the info) will be updated/recomputed.
|
||||||
func (rl *Instance) SetInfoText(s string) {
|
func (rl *Readline) SetInfoText(s string) {
|
||||||
rl.infoText = []rune(s)
|
rl.infoText = []rune(s)
|
||||||
rl.renderHelpers()
|
rl.renderHelpers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) getInfoText() {
|
func (rl *Readline) getInfoText() {
|
||||||
|
|
||||||
if !rl.modeAutoFind && !rl.modeTabFind {
|
if !rl.modeAutoFind && !rl.modeTabFind {
|
||||||
// Return if no infos provided by the user/engine
|
// Return if no infos provided by the user/engine
|
||||||
@ -25,7 +25,7 @@ func (rl *Instance) getInfoText() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeInfoText - only writes the info text and computes its offsets.
|
// writeInfoText - only writes the info text and computes its offsets.
|
||||||
func (rl *Instance) writeInfoText() {
|
func (rl *Readline) writeInfoText() {
|
||||||
if len(rl.infoText) == 0 {
|
if len(rl.infoText) == 0 {
|
||||||
rl.infoY = 0
|
rl.infoY = 0
|
||||||
return
|
return
|
||||||
@ -50,7 +50,7 @@ func (rl *Instance) writeInfoText() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) resetInfoText() {
|
func (rl *Readline) resetInfoText() {
|
||||||
rl.infoY = 0
|
rl.infoY = 0
|
||||||
rl.infoText = []rune{}
|
rl.infoText = []rune{}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,10 @@ import (
|
|||||||
// Instance is used to encapsulate the parameter group and run time of any given
|
// Instance is used to encapsulate the parameter group and run time of any given
|
||||||
// readline instance so that you can reuse the readline API for multiple entry
|
// readline instance so that you can reuse the readline API for multiple entry
|
||||||
// captures without having to repeatedly unload configuration.
|
// captures without having to repeatedly unload configuration.
|
||||||
type Instance struct {
|
|
||||||
|
// #type
|
||||||
|
// blah blah
|
||||||
|
type Readline struct {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Input Modes -------------------------------------------------------------------------------
|
// Input Modes -------------------------------------------------------------------------------
|
||||||
@ -213,8 +216,8 @@ type Instance struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
func NewInstance() *Instance {
|
func NewInstance() *Readline {
|
||||||
rl := new(Instance)
|
rl := new(Readline)
|
||||||
|
|
||||||
// Prompt
|
// Prompt
|
||||||
rl.Multiline = false
|
rl.Multiline = false
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
// When the DelayedSyntaxWorker gives us a new line, we need to check if there
|
// When the DelayedSyntaxWorker gives us a new line, we need to check if there
|
||||||
// is any processing to be made, that all lines match in terms of content.
|
// is any processing to be made, that all lines match in terms of content.
|
||||||
func (rl *Instance) updateLine(line []rune) {
|
func (rl *Readline) updateLine(line []rune) {
|
||||||
if len(rl.currentComp) > 0 {
|
if len(rl.currentComp) > 0 {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -18,7 +18,7 @@ func (rl *Instance) updateLine(line []rune) {
|
|||||||
|
|
||||||
// getLine - In many places we need the current line input. We either return the real line,
|
// getLine - In many places we need the current line input. We either return the real line,
|
||||||
// or the one that includes the current completion candidate, if there is any.
|
// or the one that includes the current completion candidate, if there is any.
|
||||||
func (rl *Instance) GetLine() []rune {
|
func (rl *Readline) GetLine() []rune {
|
||||||
if len(rl.currentComp) > 0 {
|
if len(rl.currentComp) > 0 {
|
||||||
return rl.lineComp
|
return rl.lineComp
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ func (rl *Instance) GetLine() []rune {
|
|||||||
// function is only ever called once, and after having moved back to prompt position
|
// function is only ever called once, and after having moved back to prompt position
|
||||||
// and having printed the line: this is so that at any moment, everyone has the good
|
// and having printed the line: this is so that at any moment, everyone has the good
|
||||||
// values for moving around, synchronized with the update input line.
|
// values for moving around, synchronized with the update input line.
|
||||||
func (rl *Instance) echo() {
|
func (rl *Readline) echo() {
|
||||||
|
|
||||||
// Then we print the prompt, and the line,
|
// Then we print the prompt, and the line,
|
||||||
hideCursor()
|
hideCursor()
|
||||||
@ -79,7 +79,7 @@ func (rl *Instance) echo() {
|
|||||||
unhideCursor()
|
unhideCursor()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) insert(r []rune) {
|
func (rl *Readline) insert(r []rune) {
|
||||||
for {
|
for {
|
||||||
// I don't really understand why `0` is creaping in at the end of the
|
// I don't really understand why `0` is creaping in at the end of the
|
||||||
// array but it only happens with unicode characters.
|
// array but it only happens with unicode characters.
|
||||||
@ -112,11 +112,11 @@ func (rl *Instance) insert(r []rune) {
|
|||||||
rl.updateHelpers()
|
rl.updateHelpers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) Insert(t string) {
|
func (rl *Readline) Insert(t string) {
|
||||||
rl.insert([]rune(t))
|
rl.insert([]rune(t))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) deleteX() {
|
func (rl *Readline) deleteX() {
|
||||||
switch {
|
switch {
|
||||||
case len(rl.line) == 0:
|
case len(rl.line) == 0:
|
||||||
return
|
return
|
||||||
@ -134,7 +134,7 @@ func (rl *Instance) deleteX() {
|
|||||||
rl.updateHelpers()
|
rl.updateHelpers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) deleteBackspace(forward bool) {
|
func (rl *Readline) deleteBackspace(forward bool) {
|
||||||
switch {
|
switch {
|
||||||
case len(rl.line) == 0:
|
case len(rl.line) == 0:
|
||||||
return
|
return
|
||||||
@ -153,7 +153,7 @@ func (rl *Instance) deleteBackspace(forward bool) {
|
|||||||
rl.updateHelpers()
|
rl.updateHelpers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) clearLine() {
|
func (rl *Readline) clearLine() {
|
||||||
if len(rl.line) == 0 {
|
if len(rl.line) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -179,21 +179,21 @@ func (rl *Instance) clearLine() {
|
|||||||
rl.clearVirtualComp()
|
rl.clearVirtualComp()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) deleteToBeginning() {
|
func (rl *Readline) deleteToBeginning() {
|
||||||
rl.resetVirtualComp(false)
|
rl.resetVirtualComp(false)
|
||||||
// Keep the line length up until the cursor
|
// Keep the line length up until the cursor
|
||||||
rl.line = rl.line[rl.pos:]
|
rl.line = rl.line[rl.pos:]
|
||||||
rl.pos = 0
|
rl.pos = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) deleteToEnd() {
|
func (rl *Readline) deleteToEnd() {
|
||||||
rl.resetVirtualComp(false)
|
rl.resetVirtualComp(false)
|
||||||
// Keep everything before the cursor
|
// Keep everything before the cursor
|
||||||
rl.line = rl.line[:rl.pos]
|
rl.line = rl.line[:rl.pos]
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO(Renzix): move to emacs sepecific file
|
// @TODO(Renzix): move to emacs sepecific file
|
||||||
func (rl *Instance) emacsForwardWord(tokeniser tokeniser) (adjust int) {
|
func (rl *Readline) emacsForwardWord(tokeniser tokeniser) (adjust int) {
|
||||||
split, index, pos := tokeniser(rl.line, rl.pos)
|
split, index, pos := tokeniser(rl.line, rl.pos)
|
||||||
if len(split) == 0 {
|
if len(split) == 0 {
|
||||||
return
|
return
|
||||||
@ -214,7 +214,7 @@ func (rl *Instance) emacsForwardWord(tokeniser tokeniser) (adjust int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) emacsBackwardWord(tokeniser tokeniser) (adjust int) {
|
func (rl *Readline) emacsBackwardWord(tokeniser tokeniser) (adjust int) {
|
||||||
split, index, pos := tokeniser(rl.line, rl.pos)
|
split, index, pos := tokeniser(rl.line, rl.pos)
|
||||||
if len(split) == 0 {
|
if len(split) == 0 {
|
||||||
return
|
return
|
||||||
|
@ -17,17 +17,17 @@ import (
|
|||||||
|
|
||||||
var rlMetaKey = rt.StringValue("__readline")
|
var rlMetaKey = rt.StringValue("__readline")
|
||||||
|
|
||||||
func (rl *Instance) luaLoader(rtm *rt.Runtime) (rt.Value, func()) {
|
func (rl *Readline) luaLoader(rtm *rt.Runtime) (rt.Value, func()) {
|
||||||
rlMethods := rt.NewTable()
|
rlMethods := rt.NewTable()
|
||||||
rlMethodss := map[string]util.LuaExport{
|
rlMethodss := map[string]util.LuaExport{
|
||||||
"deleteByAmount": {luaDeleteByAmount, 2, false},
|
"deleteByAmount": {rlDeleteByAmount, 2, false},
|
||||||
"getLine": {luaGetLine, 1, false},
|
"getLine": {rlGetLine, 1, false},
|
||||||
"getVimRegister": {luaGetRegister, 2, false},
|
"getVimRegister": {rlGetRegister, 2, false},
|
||||||
"insert": {luaInsert, 2, false},
|
"insert": {rlInsert, 2, false},
|
||||||
"read": {luaRead, 1, false},
|
"read": {rlRead, 1, false},
|
||||||
"readChar": {luaReadChar, 1, false},
|
"readChar": {rlReadChar, 1, false},
|
||||||
"setVimRegister": {luaSetRegister, 3, false},
|
"setVimRegister": {rlSetRegister, 3, false},
|
||||||
"log": {luaLog, 2, false},
|
"log": {rlLog, 2, false},
|
||||||
}
|
}
|
||||||
util.SetExports(rtm, rlMethods, rlMethodss)
|
util.SetExports(rtm, rlMethods, rlMethodss)
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ func (rl *Instance) luaLoader(rtm *rt.Runtime) (rt.Value, func()) {
|
|||||||
rtm.SetRegistry(rlMetaKey, rt.TableValue(rlMeta))
|
rtm.SetRegistry(rlMetaKey, rt.TableValue(rlMeta))
|
||||||
|
|
||||||
rlFuncs := map[string]util.LuaExport{
|
rlFuncs := map[string]util.LuaExport{
|
||||||
"new": {luaNew, 0, false},
|
"new": {rlNew, 0, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
luaRl := rt.NewTable()
|
luaRl := rt.NewTable()
|
||||||
@ -57,14 +57,20 @@ func (rl *Instance) luaLoader(rtm *rt.Runtime) (rt.Value, func()) {
|
|||||||
return rt.TableValue(luaRl), nil
|
return rt.TableValue(luaRl), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func luaNew(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
// new() -> @Readline
|
||||||
|
// Creates a new readline instance.
|
||||||
|
func rlNew(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
rl := NewInstance()
|
rl := NewInstance()
|
||||||
ud := rlUserData(t.Runtime, rl)
|
ud := rlUserData(t.Runtime, rl)
|
||||||
|
|
||||||
return c.PushingNext1(t.Runtime, rt.UserDataValue(ud)), nil
|
return c.PushingNext1(t.Runtime, rt.UserDataValue(ud)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func luaInsert(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
// #member
|
||||||
|
// insert(text)
|
||||||
|
// Inserts text into the Hilbish command line.
|
||||||
|
// #param text string
|
||||||
|
func rlInsert(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
|
||||||
}
|
}
|
||||||
@ -84,7 +90,10 @@ func luaInsert(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func luaRead(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
// #member
|
||||||
|
// read() -> string
|
||||||
|
// Reads input from the user.
|
||||||
|
func rlRead(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -105,11 +114,12 @@ func luaRead(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||||||
return c.PushingNext1(t.Runtime, rt.StringValue(inp)), nil
|
return c.PushingNext1(t.Runtime, rt.StringValue(inp)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #member
|
||||||
// setVimRegister(register, text)
|
// setVimRegister(register, text)
|
||||||
// Sets the vim register at `register` to hold the passed text.
|
// Sets the vim register at `register` to hold the passed text.
|
||||||
// #param register string
|
// #param register string
|
||||||
// #param text string
|
// #param text string
|
||||||
func luaSetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func rlSetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.CheckNArgs(3); err != nil {
|
if err := c.CheckNArgs(3); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -134,10 +144,11 @@ func luaSetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #member
|
||||||
// getVimRegister(register) -> string
|
// getVimRegister(register) -> string
|
||||||
// Returns the text that is at the register.
|
// Returns the text that is at the register.
|
||||||
// #param register string
|
// #param register string
|
||||||
func luaGetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func rlGetRegister(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,10 +168,11 @@ func luaGetRegister(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||||||
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
|
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #member
|
||||||
// getLine() -> string
|
// getLine() -> string
|
||||||
// Returns the current input line.
|
// Returns the current input line.
|
||||||
// #returns string
|
// #returns string
|
||||||
func luaGetLine(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func rlGetLine(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -175,9 +187,10 @@ func luaGetLine(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||||||
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
|
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #member
|
||||||
// getChar() -> string
|
// getChar() -> string
|
||||||
// Reads a keystroke from the user. This is in a format of something like Ctrl-L.
|
// Reads a keystroke from the user. This is in a format of something like Ctrl-L.
|
||||||
func luaReadChar(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func rlReadChar(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
||||||
if err := c.Check1Arg(); err != nil {
|
if err := c.Check1Arg(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -191,10 +204,11 @@ func luaReadChar(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||||||
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
|
return c.PushingNext1(t.Runtime, rt.StringValue(string(buf))), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #member
|
||||||
// deleteByAmount(amount)
|
// deleteByAmount(amount)
|
||||||
// Deletes characters in the line by the given amount.
|
// Deletes characters in the line by the given amount.
|
||||||
// #param amount number
|
// #param amount number
|
||||||
func luaDeleteByAmount(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
func rlDeleteByAmount(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
|
||||||
}
|
}
|
||||||
@ -214,7 +228,10 @@ func luaDeleteByAmount(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func luaLog(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
// #member
|
||||||
|
// log(text)
|
||||||
|
// Prints a message *before* the prompt without it being interrupted by user input.
|
||||||
|
func rlLog(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
|
||||||
}
|
}
|
||||||
@ -234,7 +251,7 @@ func luaLog(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
|
|||||||
return c.Next(), nil
|
return c.Next(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func rlArg(c *rt.GoCont, arg int) (*Instance, error) {
|
func rlArg(c *rt.GoCont, arg int) (*Readline, error) {
|
||||||
j, ok := valueToRl(c.Arg(arg))
|
j, ok := valueToRl(c.Arg(arg))
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("#%d must be a readline", arg+1)
|
return nil, fmt.Errorf("#%d must be a readline", arg+1)
|
||||||
@ -243,17 +260,17 @@ func rlArg(c *rt.GoCont, arg int) (*Instance, error) {
|
|||||||
return j, nil
|
return j, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func valueToRl(val rt.Value) (*Instance, bool) {
|
func valueToRl(val rt.Value) (*Readline, bool) {
|
||||||
u, ok := val.TryUserData()
|
u, ok := val.TryUserData()
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
j, ok := u.Value().(*Instance)
|
j, ok := u.Value().(*Readline)
|
||||||
return j, ok
|
return j, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func rlUserData(rtm *rt.Runtime, rl *Instance) *rt.UserData {
|
func rlUserData(rtm *rt.Runtime, rl *Readline) *rt.UserData {
|
||||||
rlMeta := rtm.Registry(rlMetaKey)
|
rlMeta := rtm.Registry(rlMetaKey)
|
||||||
return rt.NewUserData(rl, rlMeta.AsTable())
|
return rt.NewUserData(rl, rlMeta.AsTable())
|
||||||
}
|
}
|
||||||
|
@ -8,20 +8,20 @@ import (
|
|||||||
|
|
||||||
// SetPrompt will define the readline prompt string.
|
// SetPrompt will define the readline prompt string.
|
||||||
// It also calculates the runes in the string as well as any non-printable escape codes.
|
// It also calculates the runes in the string as well as any non-printable escape codes.
|
||||||
func (rl *Instance) SetPrompt(s string) {
|
func (rl *Readline) SetPrompt(s string) {
|
||||||
rl.mainPrompt = s
|
rl.mainPrompt = s
|
||||||
rl.computePrompt()
|
rl.computePrompt()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRightPrompt sets the right prompt.
|
// SetRightPrompt sets the right prompt.
|
||||||
func (rl *Instance) SetRightPrompt(s string) {
|
func (rl *Readline) SetRightPrompt(s string) {
|
||||||
rl.rightPrompt = s + " "
|
rl.rightPrompt = s + " "
|
||||||
rl.computePrompt()
|
rl.computePrompt()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefreshPromptLog - A simple function to print a string message (a log, or more broadly,
|
// RefreshPromptLog - A simple function to print a string message (a log, or more broadly,
|
||||||
// an asynchronous event) without bothering the user, and by "pushing" the prompt below the message.
|
// an asynchronous event) without bothering the user, and by "pushing" the prompt below the message.
|
||||||
func (rl *Instance) RefreshPromptLog(log string) (err error) {
|
func (rl *Readline) RefreshPromptLog(log string) (err error) {
|
||||||
|
|
||||||
// We adjust cursor movement, depending on which mode we're currently in.
|
// We adjust cursor movement, depending on which mode we're currently in.
|
||||||
if !rl.modeTabCompletion {
|
if !rl.modeTabCompletion {
|
||||||
@ -73,7 +73,7 @@ func (rl *Instance) RefreshPromptLog(log string) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RefreshPromptInPlace - Refreshes the prompt in the very same place he is.
|
// RefreshPromptInPlace - Refreshes the prompt in the very same place he is.
|
||||||
func (rl *Instance) RefreshPromptInPlace(prompt string) (err error) {
|
func (rl *Readline) RefreshPromptInPlace(prompt string) (err error) {
|
||||||
// We adjust cursor movement, depending on which mode we're currently in.
|
// We adjust cursor movement, depending on which mode we're currently in.
|
||||||
// Prompt data intependent
|
// Prompt data intependent
|
||||||
if !rl.modeTabCompletion {
|
if !rl.modeTabCompletion {
|
||||||
@ -117,7 +117,7 @@ func (rl *Instance) RefreshPromptInPlace(prompt string) (err error) {
|
|||||||
// @prompt => If not nil (""), will use this prompt instead of the currently set prompt.
|
// @prompt => If not nil (""), will use this prompt instead of the currently set prompt.
|
||||||
// @offset => Used to set the number of lines to go upward, before reprinting. Set to 0 if not used.
|
// @offset => Used to set the number of lines to go upward, before reprinting. Set to 0 if not used.
|
||||||
// @clearLine => If true, will clean the current input line on the next refresh.
|
// @clearLine => If true, will clean the current input line on the next refresh.
|
||||||
func (rl *Instance) RefreshPromptCustom(prompt string, offset int, clearLine bool) (err error) {
|
func (rl *Readline) RefreshPromptCustom(prompt string, offset int, clearLine bool) (err error) {
|
||||||
|
|
||||||
// We adjust cursor movement, depending on which mode we're currently in.
|
// We adjust cursor movement, depending on which mode we're currently in.
|
||||||
if !rl.modeTabCompletion {
|
if !rl.modeTabCompletion {
|
||||||
@ -166,7 +166,7 @@ func (rl *Instance) RefreshPromptCustom(prompt string, offset int, clearLine boo
|
|||||||
|
|
||||||
// computePrompt - At any moment, returns an (1st or 2nd line) actualized prompt,
|
// computePrompt - At any moment, returns an (1st or 2nd line) actualized prompt,
|
||||||
// considering all input mode parameters and prompt string values.
|
// considering all input mode parameters and prompt string values.
|
||||||
func (rl *Instance) computePrompt() (prompt []rune) {
|
func (rl *Readline) computePrompt() (prompt []rune) {
|
||||||
if rl.Multiline {
|
if rl.Multiline {
|
||||||
if rl.MultilinePrompt != "" {
|
if rl.MultilinePrompt != "" {
|
||||||
rl.realPrompt = []rune(rl.MultilinePrompt)
|
rl.realPrompt = []rune(rl.MultilinePrompt)
|
||||||
@ -194,7 +194,7 @@ func (rl *Instance) computePrompt() (prompt []rune) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) colorizeVimPrompt(p []rune) (cp []rune) {
|
func (rl *Readline) colorizeVimPrompt(p []rune) (cp []rune) {
|
||||||
if rl.VimModeColorize {
|
if rl.VimModeColorize {
|
||||||
return []rune(fmt.Sprintf("%s%s%s", BOLD, string(p), RESET))
|
return []rune(fmt.Sprintf("%s%s%s", BOLD, string(p), RESET))
|
||||||
}
|
}
|
||||||
@ -211,8 +211,8 @@ func getRealLength(s string) (l int) {
|
|||||||
return getWidth([]rune(stripped))
|
return getWidth([]rune(stripped))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) echoRightPrompt() {
|
func (rl *Readline) echoRightPrompt() {
|
||||||
if rl.fullX < GetTermWidth() - rl.rightPromptLen - 1 {
|
if rl.fullX < GetTermWidth()-rl.rightPromptLen-1 {
|
||||||
moveCursorForwards(GetTermWidth())
|
moveCursorForwards(GetTermWidth())
|
||||||
moveCursorBackwards(rl.rightPromptLen)
|
moveCursorBackwards(rl.rightPromptLen)
|
||||||
print(rl.rightPrompt)
|
print(rl.rightPrompt)
|
||||||
|
@ -2,16 +2,6 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package terminal provides support functions for dealing with terminals, as
|
|
||||||
// commonly found on UNIX systems.
|
|
||||||
//
|
|
||||||
// Putting a terminal into raw mode is the most common requirement:
|
|
||||||
//
|
|
||||||
// oldState, err := terminal.MakeRaw(0)
|
|
||||||
// if err != nil {
|
|
||||||
// panic(err)
|
|
||||||
// }
|
|
||||||
// defer terminal.Restore(0, oldState)
|
|
||||||
package readline
|
package readline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -2,18 +2,9 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build windows
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
// Package terminal provides support functions for dealing with terminals, as
|
|
||||||
// commonly found on UNIX systems.
|
|
||||||
//
|
|
||||||
// Putting a terminal into raw mode is the most common requirement:
|
|
||||||
//
|
|
||||||
// oldState, err := terminal.MakeRaw(0)
|
|
||||||
// if err != nil {
|
|
||||||
// panic(err)
|
|
||||||
// }
|
|
||||||
// defer terminal.Restore(0, oldState)
|
|
||||||
package readline
|
package readline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -70,4 +61,3 @@ func GetSize(fd int) (width, height int, err error) {
|
|||||||
}
|
}
|
||||||
return int(info.Size.X), int(info.Size.Y), nil
|
return int(info.Size.X), int(info.Size.Y), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ var rxMultiline = regexp.MustCompile(`[\r\n]+`)
|
|||||||
|
|
||||||
// Readline displays the readline prompt.
|
// Readline displays the readline prompt.
|
||||||
// It will return a string (user entered data) or an error.
|
// It will return a string (user entered data) or an error.
|
||||||
func (rl *Instance) Readline() (string, error) {
|
func (rl *Readline) Readline() (string, error) {
|
||||||
fd := int(os.Stdin.Fd())
|
fd := int(os.Stdin.Fd())
|
||||||
state, err := MakeRaw(fd)
|
state, err := MakeRaw(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -183,7 +183,7 @@ func (rl *Instance) Readline() (string, error) {
|
|||||||
if rl.modeTabFind {
|
if rl.modeTabFind {
|
||||||
rl.backspaceTabFind()
|
rl.backspaceTabFind()
|
||||||
} else {
|
} else {
|
||||||
if (rl.pos < len(rl.line)) {
|
if rl.pos < len(rl.line) {
|
||||||
rl.deleteBackspace(true)
|
rl.deleteBackspace(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -545,7 +545,7 @@ func (rl *Instance) Readline() (string, error) {
|
|||||||
// editorInput is an unexported function used to determine what mode of text
|
// editorInput is an unexported function used to determine what mode of text
|
||||||
// entry readline is currently configured for and then update the line entries
|
// entry readline is currently configured for and then update the line entries
|
||||||
// accordingly.
|
// accordingly.
|
||||||
func (rl *Instance) editorInput(r []rune) {
|
func (rl *Readline) editorInput(r []rune) {
|
||||||
if len(r) == 0 {
|
if len(r) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -595,7 +595,7 @@ func (rl *Instance) editorInput(r []rune) {
|
|||||||
|
|
||||||
// viEscape - In case th user is using Vim input, and the escape sequence has not
|
// viEscape - In case th user is using Vim input, and the escape sequence has not
|
||||||
// been handled by other cases, we dispatch it to Vim and handle a few cases here.
|
// been handled by other cases, we dispatch it to Vim and handle a few cases here.
|
||||||
func (rl *Instance) viEscape(r []rune) {
|
func (rl *Readline) viEscape(r []rune) {
|
||||||
|
|
||||||
// Sometimes the escape sequence is interleaved with another one,
|
// Sometimes the escape sequence is interleaved with another one,
|
||||||
// but key strokes might be in the wrong order, so we double check
|
// but key strokes might be in the wrong order, so we double check
|
||||||
@ -611,7 +611,7 @@ func (rl *Instance) viEscape(r []rune) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) escapeSeq(r []rune) {
|
func (rl *Readline) escapeSeq(r []rune) {
|
||||||
switch string(r) {
|
switch string(r) {
|
||||||
// Vim escape sequences & dispatching --------------------------------------------------------
|
// Vim escape sequences & dispatching --------------------------------------------------------
|
||||||
case string(charEscape):
|
case string(charEscape):
|
||||||
@ -755,11 +755,11 @@ func (rl *Instance) escapeSeq(r []rune) {
|
|||||||
rl.updateHelpers()
|
rl.updateHelpers()
|
||||||
return
|
return
|
||||||
|
|
||||||
case seqDelete,seqDelete2:
|
case seqDelete, seqDelete2:
|
||||||
if rl.modeTabFind {
|
if rl.modeTabFind {
|
||||||
rl.backspaceTabFind()
|
rl.backspaceTabFind()
|
||||||
} else {
|
} else {
|
||||||
if (rl.pos < len(rl.line)) {
|
if rl.pos < len(rl.line) {
|
||||||
rl.deleteBackspace(true)
|
rl.deleteBackspace(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -890,7 +890,7 @@ func (rl *Instance) escapeSeq(r []rune) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) carridgeReturn() {
|
func (rl *Readline) carridgeReturn() {
|
||||||
rl.moveCursorByAdjust(len(rl.line))
|
rl.moveCursorByAdjust(len(rl.line))
|
||||||
rl.updateHelpers()
|
rl.updateHelpers()
|
||||||
rl.clearHelpers()
|
rl.clearHelpers()
|
||||||
@ -924,7 +924,7 @@ func isMultiline(r []rune) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) allowMultiline(data []byte) bool {
|
func (rl *Readline) allowMultiline(data []byte) bool {
|
||||||
rl.clearHelpers()
|
rl.clearHelpers()
|
||||||
printf("\r\nWARNING: %d bytes of multiline data was dumped into the shell!", len(data))
|
printf("\r\nWARNING: %d bytes of multiline data was dumped into the shell!", len(data))
|
||||||
for {
|
for {
|
||||||
|
@ -23,7 +23,7 @@ type registers struct {
|
|||||||
mutex *sync.Mutex
|
mutex *sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) initRegisters() {
|
func (rl *Readline) initRegisters() {
|
||||||
rl.registers = ®isters{
|
rl.registers = ®isters{
|
||||||
num: make(map[int][]rune, 10),
|
num: make(map[int][]rune, 10),
|
||||||
alpha: make(map[string][]rune, 52),
|
alpha: make(map[string][]rune, 52),
|
||||||
@ -36,7 +36,7 @@ func (rl *Instance) initRegisters() {
|
|||||||
// the number of Vim iterations and we save the resulting string to the appropriate buffer.
|
// the number of Vim iterations and we save the resulting string to the appropriate buffer.
|
||||||
// It's the same as saveToRegisterTokenize, but without the need to generate tokenized &
|
// It's the same as saveToRegisterTokenize, but without the need to generate tokenized &
|
||||||
// cursor-pos-actualized versions of the input line.
|
// cursor-pos-actualized versions of the input line.
|
||||||
func (rl *Instance) saveToRegister(adjust int) {
|
func (rl *Readline) saveToRegister(adjust int) {
|
||||||
|
|
||||||
// Get the current cursor position and go the length specified.
|
// Get the current cursor position and go the length specified.
|
||||||
var begin = rl.pos
|
var begin = rl.pos
|
||||||
@ -66,7 +66,7 @@ func (rl *Instance) saveToRegister(adjust int) {
|
|||||||
// saveToRegisterTokenize - Passing a function that will move around the line in the desired way, we get
|
// saveToRegisterTokenize - Passing a function that will move around the line in the desired way, we get
|
||||||
// the number of Vim iterations and we save the resulting string to the appropriate buffer. Because we
|
// the number of Vim iterations and we save the resulting string to the appropriate buffer. Because we
|
||||||
// need the cursor position to be really moved around between calls to the jumper, we also need the tokeniser.
|
// need the cursor position to be really moved around between calls to the jumper, we also need the tokeniser.
|
||||||
func (rl *Instance) saveToRegisterTokenize(tokeniser tokeniser, jumper func(tokeniser) int, vii int) {
|
func (rl *Readline) saveToRegisterTokenize(tokeniser tokeniser, jumper func(tokeniser) int, vii int) {
|
||||||
|
|
||||||
// The register is going to have to heavily manipulate the cursor position.
|
// The register is going to have to heavily manipulate the cursor position.
|
||||||
// Remember the original one first, for the end.
|
// Remember the original one first, for the end.
|
||||||
@ -104,11 +104,11 @@ func (rl *Instance) saveToRegisterTokenize(tokeniser tokeniser, jumper func(toke
|
|||||||
// saveBufToRegister - Instead of computing the buffer ourselves based on an adjust,
|
// saveBufToRegister - Instead of computing the buffer ourselves based on an adjust,
|
||||||
// let the caller pass directly this buffer, yet relying on the register system to
|
// let the caller pass directly this buffer, yet relying on the register system to
|
||||||
// determine which register will store the buffer.
|
// determine which register will store the buffer.
|
||||||
func (rl *Instance) saveBufToRegister(buffer []rune) {
|
func (rl *Readline) saveBufToRegister(buffer []rune) {
|
||||||
rl.SetRegisterBuf(string(rl.registers.currentRegister), buffer)
|
rl.SetRegisterBuf(string(rl.registers.currentRegister), buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) SetRegisterBuf(reg string, buffer []rune) {
|
func (rl *Readline) SetRegisterBuf(reg string, buffer []rune) {
|
||||||
// We must make an immutable version of the buffer first.
|
// We must make an immutable version of the buffer first.
|
||||||
buf := string(buffer)
|
buf := string(buffer)
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ func (rl *Instance) SetRegisterBuf(reg string, buffer []rune) {
|
|||||||
|
|
||||||
// The user asked to paste a buffer onto the line, so we check from which register
|
// The user asked to paste a buffer onto the line, so we check from which register
|
||||||
// we are supposed to select the buffer, and return it to the caller for insertion.
|
// we are supposed to select the buffer, and return it to the caller for insertion.
|
||||||
func (rl *Instance) pasteFromRegister() (buffer []rune) {
|
func (rl *Readline) pasteFromRegister() (buffer []rune) {
|
||||||
|
|
||||||
// When exiting this function the currently selected register is dropped,
|
// When exiting this function the currently selected register is dropped,
|
||||||
defer rl.registers.resetRegister()
|
defer rl.registers.resetRegister()
|
||||||
@ -155,7 +155,7 @@ func (rl *Instance) pasteFromRegister() (buffer []rune) {
|
|||||||
return rl.GetFromRegister(activeRegister)
|
return rl.GetFromRegister(activeRegister)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) GetFromRegister(reg string) []rune {
|
func (rl *Readline) GetFromRegister(reg string) []rune {
|
||||||
// Find the active register, and return its content.
|
// Find the active register, and return its content.
|
||||||
num, err := strconv.Atoi(reg)
|
num, err := strconv.Atoi(reg)
|
||||||
|
|
||||||
@ -264,7 +264,7 @@ func (r *registers) resetRegister() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The user can show registers completions and insert, no matter the cursor position.
|
// The user can show registers completions and insert, no matter the cursor position.
|
||||||
func (rl *Instance) completeRegisters() (groups []*CompletionGroup) {
|
func (rl *Readline) completeRegisters() (groups []*CompletionGroup) {
|
||||||
|
|
||||||
// We set the info exceptionally
|
// We set the info exceptionally
|
||||||
info := BLUE + "-- registers --" + RESET
|
info := BLUE + "-- registers --" + RESET
|
||||||
|
@ -2,7 +2,7 @@ package readline
|
|||||||
|
|
||||||
// syntaxCompletion - applies syntax highlighting to the current input line.
|
// syntaxCompletion - applies syntax highlighting to the current input line.
|
||||||
// nothing special to note here, nor any changes envisioned.
|
// nothing special to note here, nor any changes envisioned.
|
||||||
func (rl *Instance) syntaxCompletion() {
|
func (rl *Readline) syntaxCompletion() {
|
||||||
if rl.SyntaxCompleter == nil {
|
if rl.SyntaxCompleter == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,14 @@ package readline
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/rivo/uniseg"
|
"github.com/rivo/uniseg"
|
||||||
)
|
)
|
||||||
|
|
||||||
// insertCandidateVirtual - When a completion candidate is selected, we insert it virtually in the input line:
|
// insertCandidateVirtual - When a completion candidate is selected, we insert it virtually in the input line:
|
||||||
// this will not trigger further firltering against the other candidates. Each time this function
|
// this will not trigger further firltering against the other candidates. Each time this function
|
||||||
// is called, any previous candidate is dropped, after being used for moving the cursor around.
|
// is called, any previous candidate is dropped, after being used for moving the cursor around.
|
||||||
func (rl *Instance) insertCandidateVirtual(candidate []rune) {
|
func (rl *Readline) insertCandidateVirtual(candidate []rune) {
|
||||||
for {
|
for {
|
||||||
// I don't really understand why `0` is creaping in at the end of the
|
// I don't really understand why `0` is creaping in at the end of the
|
||||||
// array but it only happens with unicode characters.
|
// array but it only happens with unicode characters.
|
||||||
@ -57,7 +58,7 @@ func (rl *Instance) insertCandidateVirtual(candidate []rune) {
|
|||||||
// Insert the current completion candidate into the input line.
|
// Insert the current completion candidate into the input line.
|
||||||
// This candidate might either be the currently selected one (white frame),
|
// This candidate might either be the currently selected one (white frame),
|
||||||
// or the only candidate available, if the total number of candidates is 1.
|
// or the only candidate available, if the total number of candidates is 1.
|
||||||
func (rl *Instance) insertCandidate() {
|
func (rl *Readline) insertCandidate() {
|
||||||
|
|
||||||
cur := rl.getCurrentGroup()
|
cur := rl.getCurrentGroup()
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ func (rl *Instance) insertCandidate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// updateVirtualComp - Either insert the current completion candidate virtually, or on the real line.
|
// updateVirtualComp - Either insert the current completion candidate virtually, or on the real line.
|
||||||
func (rl *Instance) updateVirtualComp() {
|
func (rl *Readline) updateVirtualComp() {
|
||||||
cur := rl.getCurrentGroup()
|
cur := rl.getCurrentGroup()
|
||||||
if cur != nil {
|
if cur != nil {
|
||||||
|
|
||||||
@ -118,7 +119,7 @@ func (rl *Instance) updateVirtualComp() {
|
|||||||
// resetVirtualComp - This function is called before most of our readline key handlers,
|
// resetVirtualComp - This function is called before most of our readline key handlers,
|
||||||
// and makes sure that the current completion (virtually inserted) is either inserted or dropped,
|
// and makes sure that the current completion (virtually inserted) is either inserted or dropped,
|
||||||
// and that all related parameters are reinitialized.
|
// and that all related parameters are reinitialized.
|
||||||
func (rl *Instance) resetVirtualComp(drop bool) {
|
func (rl *Readline) resetVirtualComp(drop bool) {
|
||||||
|
|
||||||
// If we don't have a current virtual completion, there's nothing to do.
|
// If we don't have a current virtual completion, there's nothing to do.
|
||||||
// IMPORTANT: this MUST be first, to avoid nil problems with empty comps.
|
// IMPORTANT: this MUST be first, to avoid nil problems with empty comps.
|
||||||
@ -196,7 +197,7 @@ func trimTrailing(comp string) (trimmed string, hadSlash bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// viDeleteByAdjustVirtual - Same as viDeleteByAdjust, but for our virtually completed input line.
|
// viDeleteByAdjustVirtual - Same as viDeleteByAdjust, but for our virtually completed input line.
|
||||||
func (rl *Instance) viDeleteByAdjustVirtual(adjust int) {
|
func (rl *Readline) viDeleteByAdjustVirtual(adjust int) {
|
||||||
var (
|
var (
|
||||||
newLine []rune
|
newLine []rune
|
||||||
backOne bool
|
backOne bool
|
||||||
@ -235,7 +236,7 @@ func (rl *Instance) viDeleteByAdjustVirtual(adjust int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// viJumpEVirtual - Same as viJumpE, but for our virtually completed input line.
|
// viJumpEVirtual - Same as viJumpE, but for our virtually completed input line.
|
||||||
func (rl *Instance) viJumpEVirtual(tokeniser func([]rune, int) ([]string, int, int)) (adjust int) {
|
func (rl *Readline) viJumpEVirtual(tokeniser func([]rune, int) ([]string, int, int)) (adjust int) {
|
||||||
split, index, pos := tokeniser(rl.lineComp, rl.pos)
|
split, index, pos := tokeniser(rl.lineComp, rl.pos)
|
||||||
if len(split) == 0 {
|
if len(split) == 0 {
|
||||||
return
|
return
|
||||||
@ -258,7 +259,7 @@ func (rl *Instance) viJumpEVirtual(tokeniser func([]rune, int) ([]string, int, i
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) deleteVirtual() {
|
func (rl *Readline) deleteVirtual() {
|
||||||
switch {
|
switch {
|
||||||
case len(rl.lineComp) == 0:
|
case len(rl.lineComp) == 0:
|
||||||
return
|
return
|
||||||
@ -274,7 +275,7 @@ func (rl *Instance) deleteVirtual() {
|
|||||||
|
|
||||||
// We are done with the current virtual completion candidate.
|
// We are done with the current virtual completion candidate.
|
||||||
// Get ready for the next one
|
// Get ready for the next one
|
||||||
func (rl *Instance) clearVirtualComp() {
|
func (rl *Readline) clearVirtualComp() {
|
||||||
rl.line = rl.lineComp
|
rl.line = rl.lineComp
|
||||||
rl.currentComp = []rune{}
|
rl.currentComp = []rune{}
|
||||||
rl.compAddSpace = false
|
rl.compAddSpace = false
|
||||||
|
@ -28,7 +28,7 @@ const (
|
|||||||
|
|
||||||
// getTabCompletion - This root function sets up all completion items and engines,
|
// getTabCompletion - This root function sets up all completion items and engines,
|
||||||
// dealing with all search and completion modes. But it does not perform printing.
|
// dealing with all search and completion modes. But it does not perform printing.
|
||||||
func (rl *Instance) getTabCompletion() {
|
func (rl *Readline) getTabCompletion() {
|
||||||
|
|
||||||
// Populate registers if requested.
|
// Populate registers if requested.
|
||||||
if rl.modeAutoFind && rl.searchMode == RegisterFind {
|
if rl.modeAutoFind && rl.searchMode == RegisterFind {
|
||||||
@ -53,7 +53,7 @@ func (rl *Instance) getTabCompletion() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getRegisterCompletion - Populates and sets up completion for Vim registers.
|
// getRegisterCompletion - Populates and sets up completion for Vim registers.
|
||||||
func (rl *Instance) getRegisterCompletion() {
|
func (rl *Readline) getRegisterCompletion() {
|
||||||
|
|
||||||
rl.tcGroups = rl.completeRegisters()
|
rl.tcGroups = rl.completeRegisters()
|
||||||
if len(rl.tcGroups) == 0 {
|
if len(rl.tcGroups) == 0 {
|
||||||
@ -84,7 +84,7 @@ func (rl *Instance) getRegisterCompletion() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getTabSearchCompletion - Populates and sets up completion for completion search.
|
// getTabSearchCompletion - Populates and sets up completion for completion search.
|
||||||
func (rl *Instance) getTabSearchCompletion() {
|
func (rl *Readline) getTabSearchCompletion() {
|
||||||
|
|
||||||
// Get completions from the engine, and make sure there is a current group.
|
// Get completions from the engine, and make sure there is a current group.
|
||||||
rl.getCompletions()
|
rl.getCompletions()
|
||||||
@ -94,7 +94,7 @@ func (rl *Instance) getTabSearchCompletion() {
|
|||||||
rl.getCurrentGroup()
|
rl.getCurrentGroup()
|
||||||
|
|
||||||
// Set the info for this completion mode
|
// Set the info for this completion mode
|
||||||
rl.infoText = append([]rune("Completion search: " + UNDERLINE + BOLD), rl.tfLine...)
|
rl.infoText = append([]rune("Completion search: "+UNDERLINE+BOLD), rl.tfLine...)
|
||||||
|
|
||||||
for _, g := range rl.tcGroups {
|
for _, g := range rl.tcGroups {
|
||||||
g.updateTabFind(rl)
|
g.updateTabFind(rl)
|
||||||
@ -107,7 +107,7 @@ func (rl *Instance) getTabSearchCompletion() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getHistorySearchCompletion - Populates and sets up completion for command history search
|
// getHistorySearchCompletion - Populates and sets up completion for command history search
|
||||||
func (rl *Instance) getHistorySearchCompletion() {
|
func (rl *Readline) getHistorySearchCompletion() {
|
||||||
|
|
||||||
// Refresh full list each time
|
// Refresh full list each time
|
||||||
rl.tcGroups = rl.completeHistory()
|
rl.tcGroups = rl.completeHistory()
|
||||||
@ -142,7 +142,7 @@ func (rl *Instance) getHistorySearchCompletion() {
|
|||||||
|
|
||||||
// getNormalCompletion - Populates and sets up completion for normal comp mode.
|
// getNormalCompletion - Populates and sets up completion for normal comp mode.
|
||||||
// Will automatically cancel the completion mode if there are no candidates.
|
// Will automatically cancel the completion mode if there are no candidates.
|
||||||
func (rl *Instance) getNormalCompletion() {
|
func (rl *Readline) getNormalCompletion() {
|
||||||
|
|
||||||
// Get completions groups, pass delayedTabContext and check nils
|
// Get completions groups, pass delayedTabContext and check nils
|
||||||
rl.getCompletions()
|
rl.getCompletions()
|
||||||
@ -172,7 +172,7 @@ func (rl *Instance) getNormalCompletion() {
|
|||||||
// getCompletions - Calls the completion engine/function to yield a list of 0 or more completion groups,
|
// getCompletions - Calls the completion engine/function to yield a list of 0 or more completion groups,
|
||||||
// sets up a delayed tab context and passes it on to the tab completion engine function, and ensure no
|
// sets up a delayed tab context and passes it on to the tab completion engine function, and ensure no
|
||||||
// nil groups/items will pass through. This function is called by different comp search/nav modes.
|
// nil groups/items will pass through. This function is called by different comp search/nav modes.
|
||||||
func (rl *Instance) getCompletions() {
|
func (rl *Readline) getCompletions() {
|
||||||
|
|
||||||
// If there is no wired tab completion engine, nothing we can do.
|
// If there is no wired tab completion engine, nothing we can do.
|
||||||
if rl.TabCompleter == nil {
|
if rl.TabCompleter == nil {
|
||||||
@ -214,7 +214,7 @@ func (rl *Instance) getCompletions() {
|
|||||||
|
|
||||||
// moveTabCompletionHighlight - This function is in charge of
|
// moveTabCompletionHighlight - This function is in charge of
|
||||||
// computing the new position in the current completions liste.
|
// computing the new position in the current completions liste.
|
||||||
func (rl *Instance) moveTabCompletionHighlight(x, y int) {
|
func (rl *Readline) moveTabCompletionHighlight(x, y int) {
|
||||||
rl.completionOpen = true
|
rl.completionOpen = true
|
||||||
g := rl.getCurrentGroup()
|
g := rl.getCurrentGroup()
|
||||||
|
|
||||||
@ -253,7 +253,7 @@ func (rl *Instance) moveTabCompletionHighlight(x, y int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// writeTabCompletion - Prints all completion groups and their items
|
// writeTabCompletion - Prints all completion groups and their items
|
||||||
func (rl *Instance) writeTabCompletion() {
|
func (rl *Readline) writeTabCompletion() {
|
||||||
|
|
||||||
// The final completions string to print.
|
// The final completions string to print.
|
||||||
var completions string
|
var completions string
|
||||||
@ -289,7 +289,7 @@ func (rl *Instance) writeTabCompletion() {
|
|||||||
// cropCompletions - When the user cycles through a completion list longer
|
// cropCompletions - When the user cycles through a completion list longer
|
||||||
// than the console MaxTabCompleterRows value, we crop the completions string
|
// than the console MaxTabCompleterRows value, we crop the completions string
|
||||||
// so that "global" cycling (across all groups) is printed correctly.
|
// so that "global" cycling (across all groups) is printed correctly.
|
||||||
func (rl *Instance) cropCompletions(comps string) (cropped string, usedY int) {
|
func (rl *Readline) cropCompletions(comps string) (cropped string, usedY int) {
|
||||||
|
|
||||||
// If we actually fit into the MaxTabCompleterRows, return the comps
|
// If we actually fit into the MaxTabCompleterRows, return the comps
|
||||||
if rl.tcUsedY < rl.MaxTabCompleterRows {
|
if rl.tcUsedY < rl.MaxTabCompleterRows {
|
||||||
@ -366,7 +366,7 @@ func (rl *Instance) cropCompletions(comps string) (cropped string, usedY int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) getAbsPos() int {
|
func (rl *Readline) getAbsPos() int {
|
||||||
var prev int
|
var prev int
|
||||||
var foundCurrent bool
|
var foundCurrent bool
|
||||||
for _, grp := range rl.tcGroups {
|
for _, grp := range rl.tcGroups {
|
||||||
@ -390,7 +390,7 @@ func (rl *Instance) getAbsPos() int {
|
|||||||
|
|
||||||
// We pass a special subset of the current input line, so that
|
// We pass a special subset of the current input line, so that
|
||||||
// completions are available no matter where the cursor is.
|
// completions are available no matter where the cursor is.
|
||||||
func (rl *Instance) getCompletionLine() (line []rune, pos int) {
|
func (rl *Readline) getCompletionLine() (line []rune, pos int) {
|
||||||
|
|
||||||
pos = rl.pos - len(rl.currentComp)
|
pos = rl.pos - len(rl.currentComp)
|
||||||
if pos < 0 {
|
if pos < 0 {
|
||||||
@ -409,7 +409,7 @@ func (rl *Instance) getCompletionLine() (line []rune, pos int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) getCurrentGroup() (group *CompletionGroup) {
|
func (rl *Readline) getCurrentGroup() (group *CompletionGroup) {
|
||||||
for _, g := range rl.tcGroups {
|
for _, g := range rl.tcGroups {
|
||||||
if g.isCurrent && len(g.Suggestions) > 0 {
|
if g.isCurrent && len(g.Suggestions) > 0 {
|
||||||
return g
|
return g
|
||||||
@ -431,7 +431,7 @@ func (rl *Instance) getCurrentGroup() (group *CompletionGroup) {
|
|||||||
|
|
||||||
// cycleNextGroup - Finds either the first non-empty group,
|
// cycleNextGroup - Finds either the first non-empty group,
|
||||||
// or the next non-empty group after the current one.
|
// or the next non-empty group after the current one.
|
||||||
func (rl *Instance) cycleNextGroup() {
|
func (rl *Readline) cycleNextGroup() {
|
||||||
for i, g := range rl.tcGroups {
|
for i, g := range rl.tcGroups {
|
||||||
if g.isCurrent {
|
if g.isCurrent {
|
||||||
g.isCurrent = false
|
g.isCurrent = false
|
||||||
@ -452,7 +452,7 @@ func (rl *Instance) cycleNextGroup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cyclePreviousGroup - Same as cycleNextGroup but reverse
|
// cyclePreviousGroup - Same as cycleNextGroup but reverse
|
||||||
func (rl *Instance) cyclePreviousGroup() {
|
func (rl *Readline) cyclePreviousGroup() {
|
||||||
for i, g := range rl.tcGroups {
|
for i, g := range rl.tcGroups {
|
||||||
if g.isCurrent {
|
if g.isCurrent {
|
||||||
g.isCurrent = false
|
g.isCurrent = false
|
||||||
@ -471,7 +471,7 @@ func (rl *Instance) cyclePreviousGroup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if we have a single completion candidate
|
// Check if we have a single completion candidate
|
||||||
func (rl *Instance) hasOneCandidate() bool {
|
func (rl *Readline) hasOneCandidate() bool {
|
||||||
if len(rl.tcGroups) == 0 {
|
if len(rl.tcGroups) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -509,7 +509,7 @@ func (rl *Instance) hasOneCandidate() bool {
|
|||||||
// - The user-specified max completion length
|
// - The user-specified max completion length
|
||||||
// - The terminal lengh
|
// - The terminal lengh
|
||||||
// we use this function to prompt for confirmation before printing comps.
|
// we use this function to prompt for confirmation before printing comps.
|
||||||
func (rl *Instance) promptCompletionConfirm(sentence string) {
|
func (rl *Readline) promptCompletionConfirm(sentence string) {
|
||||||
rl.infoText = []rune(sentence)
|
rl.infoText = []rune(sentence)
|
||||||
|
|
||||||
rl.compConfirmWait = true
|
rl.compConfirmWait = true
|
||||||
@ -518,7 +518,7 @@ func (rl *Instance) promptCompletionConfirm(sentence string) {
|
|||||||
rl.renderHelpers()
|
rl.renderHelpers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) getCompletionCount() (comps int, lines int, adjusted int) {
|
func (rl *Readline) getCompletionCount() (comps int, lines int, adjusted int) {
|
||||||
for _, group := range rl.tcGroups {
|
for _, group := range rl.tcGroups {
|
||||||
comps += len(group.Suggestions)
|
comps += len(group.Suggestions)
|
||||||
// if group.Name != "" {
|
// if group.Name != "" {
|
||||||
@ -535,7 +535,7 @@ func (rl *Instance) getCompletionCount() (comps int, lines int, adjusted int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) resetTabCompletion() {
|
func (rl *Readline) resetTabCompletion() {
|
||||||
rl.modeTabCompletion = false
|
rl.modeTabCompletion = false
|
||||||
rl.tabCompletionSelect = false
|
rl.tabCompletionSelect = false
|
||||||
rl.compConfirmWait = false
|
rl.compConfirmWait = false
|
||||||
|
@ -12,7 +12,7 @@ const (
|
|||||||
RegisterFind
|
RegisterFind
|
||||||
)
|
)
|
||||||
|
|
||||||
func (rl *Instance) backspaceTabFind() {
|
func (rl *Readline) backspaceTabFind() {
|
||||||
if len(rl.tfLine) > 0 {
|
if len(rl.tfLine) > 0 {
|
||||||
rl.tfLine = rl.tfLine[:len(rl.tfLine)-1]
|
rl.tfLine = rl.tfLine[:len(rl.tfLine)-1]
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ func (rl *Instance) backspaceTabFind() {
|
|||||||
|
|
||||||
// Filter and refresh (print) a list of completions. The caller should have reset
|
// Filter and refresh (print) a list of completions. The caller should have reset
|
||||||
// the virtual completion system before, so that should not clash with this.
|
// the virtual completion system before, so that should not clash with this.
|
||||||
func (rl *Instance) updateTabFind(r []rune) {
|
func (rl *Readline) updateTabFind(r []rune) {
|
||||||
|
|
||||||
rl.tfLine = append(rl.tfLine, r...)
|
rl.tfLine = append(rl.tfLine, r...)
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ func (rl *Instance) updateTabFind(r []rune) {
|
|||||||
rl.renderHelpers()
|
rl.renderHelpers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) resetTabFind() {
|
func (rl *Readline) resetTabFind() {
|
||||||
rl.modeTabFind = false
|
rl.modeTabFind = false
|
||||||
// rl.modeAutoFind = false // Added, because otherwise it gets stuck on search completions
|
// rl.modeAutoFind = false // Added, because otherwise it gets stuck on search completions
|
||||||
|
|
||||||
|
@ -7,12 +7,12 @@ import (
|
|||||||
|
|
||||||
// DelayedTabContext is a custom context interface for async updates to the tab completions
|
// DelayedTabContext is a custom context interface for async updates to the tab completions
|
||||||
type DelayedTabContext struct {
|
type DelayedTabContext struct {
|
||||||
rl *Instance
|
rl *Readline
|
||||||
Context context.Context
|
Context context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func delayedSyntaxTimer(rl *Instance, i int64) {
|
func delayedSyntaxTimer(rl *Readline, i int64) {
|
||||||
if rl.PasswordMask != 0 || rl.DelayedSyntaxWorker == nil {
|
if rl.PasswordMask != 0 || rl.DelayedSyntaxWorker == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ type undoItem struct {
|
|||||||
pos int
|
pos int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) undoAppendHistory() {
|
func (rl *Readline) undoAppendHistory() {
|
||||||
defer func() { rl.viUndoSkipAppend = false }()
|
defer func() { rl.viUndoSkipAppend = false }()
|
||||||
|
|
||||||
if rl.viUndoSkipAppend {
|
if rl.viUndoSkipAppend {
|
||||||
@ -18,7 +18,7 @@ func (rl *Instance) undoAppendHistory() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) undoLast() {
|
func (rl *Readline) undoLast() {
|
||||||
var undo undoItem
|
var undo undoItem
|
||||||
for {
|
for {
|
||||||
if len(rl.viUndoHistory) == 0 {
|
if len(rl.viUndoHistory) == 0 {
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
// updateHelpers is a key part of the whole refresh process:
|
// updateHelpers is a key part of the whole refresh process:
|
||||||
// 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 *Readline) updateHelpers() {
|
||||||
print(seqHideCursor)
|
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()
|
||||||
@ -19,7 +19,9 @@ func (rl *Instance) updateHelpers() {
|
|||||||
if rl.modeTabCompletion && !rl.completionOpen {
|
if rl.modeTabCompletion && !rl.completionOpen {
|
||||||
rl.getTabCompletion()
|
rl.getTabCompletion()
|
||||||
} else {
|
} else {
|
||||||
if rl.completionOpen { rl.completionOpen = false }
|
if rl.completionOpen {
|
||||||
|
rl.completionOpen = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We clear everything
|
// We clear everything
|
||||||
@ -49,7 +51,7 @@ func getWidth(x []rune) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update reference should be called only once in a "loop" (not Readline(), but key control loop)
|
// Update reference should be called only once in a "loop" (not Readline(), but key control loop)
|
||||||
func (rl *Instance) updateReferences() {
|
func (rl *Readline) updateReferences() {
|
||||||
|
|
||||||
// We always need to work with clean data,
|
// We always need to work with clean data,
|
||||||
// since we will have incrementers all around
|
// since we will have incrementers all around
|
||||||
@ -103,7 +105,7 @@ func (rl *Instance) updateReferences() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) resetHelpers() {
|
func (rl *Readline) resetHelpers() {
|
||||||
rl.modeAutoFind = false
|
rl.modeAutoFind = false
|
||||||
|
|
||||||
// Now reset all below-input helpers
|
// Now reset all below-input helpers
|
||||||
@ -113,7 +115,7 @@ func (rl *Instance) resetHelpers() {
|
|||||||
|
|
||||||
// clearHelpers - Clears everything: prompt, input, Infos & comps,
|
// clearHelpers - Clears everything: prompt, input, Infos & comps,
|
||||||
// and comes back at the prompt.
|
// and comes back at the prompt.
|
||||||
func (rl *Instance) clearHelpers() {
|
func (rl *Readline) clearHelpers() {
|
||||||
|
|
||||||
// Now go down to the last line of input
|
// Now go down to the last line of input
|
||||||
moveCursorDown(rl.fullY - rl.posY)
|
moveCursorDown(rl.fullY - rl.posY)
|
||||||
@ -132,7 +134,7 @@ func (rl *Instance) clearHelpers() {
|
|||||||
// renderHelpers - pritns all components (prompt, line, Infos & comps)
|
// renderHelpers - pritns all components (prompt, line, Infos & comps)
|
||||||
// and replaces the cursor to its current position. This function never
|
// and replaces the cursor to its current position. This function never
|
||||||
// computes or refreshes any value, except from inside the echo function.
|
// computes or refreshes any value, except from inside the echo function.
|
||||||
func (rl *Instance) renderHelpers() {
|
func (rl *Readline) renderHelpers() {
|
||||||
|
|
||||||
// when the instance is in this state we want it to be "below" the user's
|
// when the instance is in this state we want it to be "below" the user's
|
||||||
// input for it to be aligned properly
|
// input for it to be aligned properly
|
||||||
@ -197,14 +199,14 @@ func (rl *Instance) renderHelpers() {
|
|||||||
moveCursorForwards(rl.posX)
|
moveCursorForwards(rl.posX)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) bufprintF(format string, a ...any) {
|
func (rl *Readline) bufprintF(format string, a ...any) {
|
||||||
fmt.Fprintf(rl.bufferedOut, format, a...)
|
fmt.Fprintf(rl.bufferedOut, format, a...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) bufprint(text string) {
|
func (rl *Readline) bufprint(text string) {
|
||||||
fmt.Fprint(rl.bufferedOut, text)
|
fmt.Fprint(rl.bufferedOut, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) bufflush() {
|
func (rl *Readline) bufflush() {
|
||||||
rl.bufferedOut.Flush()
|
rl.bufferedOut.Flush()
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ViAction int
|
type ViAction int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VimActionYank = iota
|
VimActionYank = iota
|
||||||
VimActionPaste
|
VimActionPaste
|
||||||
@ -52,7 +53,7 @@ var (
|
|||||||
// vi - Apply a key to a Vi action. Note that as in the rest of the code, all cursor movements
|
// vi - Apply a key to a Vi action. Note that as in the rest of the code, all cursor movements
|
||||||
// have been moved away, and only the rl.pos is adjusted: when echoing the input line, the shell
|
// have been moved away, and only the rl.pos is adjusted: when echoing the input line, the shell
|
||||||
// will compute the new cursor pos accordingly.
|
// will compute the new cursor pos accordingly.
|
||||||
func (rl *Instance) vi(r rune) {
|
func (rl *Readline) vi(r rune) {
|
||||||
activeRegister := string(rl.registers.currentRegister)
|
activeRegister := string(rl.registers.currentRegister)
|
||||||
|
|
||||||
// Check if we are in register mode. If yes, and for some characters,
|
// Check if we are in register mode. If yes, and for some characters,
|
||||||
@ -384,7 +385,7 @@ func (rl *Instance) vi(r rune) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) getViIterations() int {
|
func (rl *Readline) getViIterations() int {
|
||||||
i, _ := strconv.Atoi(rl.viIteration)
|
i, _ := strconv.Atoi(rl.viIteration)
|
||||||
if i < 1 {
|
if i < 1 {
|
||||||
i = 1
|
i = 1
|
||||||
@ -393,7 +394,7 @@ func (rl *Instance) getViIterations() int {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) refreshVimStatus() {
|
func (rl *Readline) refreshVimStatus() {
|
||||||
rl.ViModeCallback(rl.modeViMode)
|
rl.ViModeCallback(rl.modeViMode)
|
||||||
rl.computePrompt()
|
rl.computePrompt()
|
||||||
rl.updateHelpers()
|
rl.updateHelpers()
|
||||||
@ -401,7 +402,7 @@ func (rl *Instance) refreshVimStatus() {
|
|||||||
|
|
||||||
// viInfoMessage - lmorg's way of showing Vim status is to overwrite the info.
|
// viInfoMessage - lmorg's way of showing Vim status is to overwrite the info.
|
||||||
// Currently not used, as there is a possibility to show the current Vim mode in the prompt.
|
// Currently not used, as there is a possibility to show the current Vim mode in the prompt.
|
||||||
func (rl *Instance) viInfoMessage() {
|
func (rl *Readline) viInfoMessage() {
|
||||||
switch rl.modeViMode {
|
switch rl.modeViMode {
|
||||||
case VimKeys:
|
case VimKeys:
|
||||||
rl.infoText = []rune("-- VIM KEYS -- (press `i` to return to normal editing mode)")
|
rl.infoText = []rune("-- VIM KEYS -- (press `i` to return to normal editing mode)")
|
||||||
@ -421,7 +422,7 @@ func (rl *Instance) viInfoMessage() {
|
|||||||
rl.renderHelpers()
|
rl.renderHelpers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) viJumpB(tokeniser tokeniser) (adjust int) {
|
func (rl *Readline) viJumpB(tokeniser tokeniser) (adjust int) {
|
||||||
split, index, pos := tokeniser(rl.line, rl.pos)
|
split, index, pos := tokeniser(rl.line, rl.pos)
|
||||||
switch {
|
switch {
|
||||||
case len(split) == 0:
|
case len(split) == 0:
|
||||||
@ -436,7 +437,7 @@ func (rl *Instance) viJumpB(tokeniser tokeniser) (adjust int) {
|
|||||||
return adjust * -1
|
return adjust * -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) viJumpE(tokeniser tokeniser) (adjust int) {
|
func (rl *Readline) viJumpE(tokeniser tokeniser) (adjust int) {
|
||||||
split, index, pos := tokeniser(rl.line, rl.pos)
|
split, index, pos := tokeniser(rl.line, rl.pos)
|
||||||
if len(split) == 0 {
|
if len(split) == 0 {
|
||||||
return
|
return
|
||||||
@ -459,7 +460,7 @@ func (rl *Instance) viJumpE(tokeniser tokeniser) (adjust int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) viJumpW(tokeniser tokeniser) (adjust int) {
|
func (rl *Readline) viJumpW(tokeniser tokeniser) (adjust int) {
|
||||||
split, index, pos := tokeniser(rl.line, rl.pos)
|
split, index, pos := tokeniser(rl.line, rl.pos)
|
||||||
switch {
|
switch {
|
||||||
case len(split) == 0:
|
case len(split) == 0:
|
||||||
@ -472,7 +473,7 @@ func (rl *Instance) viJumpW(tokeniser tokeniser) (adjust int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) viJumpPreviousBrace() (adjust int) {
|
func (rl *Readline) viJumpPreviousBrace() (adjust int) {
|
||||||
if rl.pos == 0 {
|
if rl.pos == 0 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -486,7 +487,7 @@ func (rl *Instance) viJumpPreviousBrace() (adjust int) {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) viJumpNextBrace() (adjust int) {
|
func (rl *Readline) viJumpNextBrace() (adjust int) {
|
||||||
if rl.pos >= len(rl.line)-1 {
|
if rl.pos >= len(rl.line)-1 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -500,7 +501,7 @@ func (rl *Instance) viJumpNextBrace() (adjust int) {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) viJumpBracket() (adjust int) {
|
func (rl *Readline) viJumpBracket() (adjust int) {
|
||||||
split, index, pos := tokeniseBrackets(rl.line, rl.pos)
|
split, index, pos := tokeniseBrackets(rl.line, rl.pos)
|
||||||
switch {
|
switch {
|
||||||
case len(split) == 0:
|
case len(split) == 0:
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// vimDelete -
|
// vimDelete -
|
||||||
func (rl *Instance) viDelete(r rune) {
|
func (rl *Readline) viDelete(r rune) {
|
||||||
|
|
||||||
// We are allowed to type iterations after a delete ('d') command.
|
// We are allowed to type iterations after a delete ('d') command.
|
||||||
// in which case we don't exit the delete mode. The next thing typed
|
// in which case we don't exit the delete mode. The next thing typed
|
||||||
@ -91,7 +91,7 @@ func (rl *Instance) viDelete(r rune) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) viDeleteByAdjust(adjust int) {
|
func (rl *Readline) viDeleteByAdjust(adjust int) {
|
||||||
var (
|
var (
|
||||||
newLine []rune
|
newLine []rune
|
||||||
backOne bool
|
backOne bool
|
||||||
@ -142,11 +142,11 @@ func (rl *Instance) viDeleteByAdjust(adjust int) {
|
|||||||
rl.updateHelpers()
|
rl.updateHelpers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) DeleteByAmount(adjust int) {
|
func (rl *Readline) DeleteByAmount(adjust int) {
|
||||||
rl.viDeleteByAdjust(adjust)
|
rl.viDeleteByAdjust(adjust)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rl *Instance) vimDeleteToken(r rune) bool {
|
func (rl *Readline) vimDeleteToken(r rune) bool {
|
||||||
tokens, _, _ := tokeniseSplitSpaces(rl.line, 0)
|
tokens, _, _ := tokeniseSplitSpaces(rl.line, 0)
|
||||||
pos := int(r) - 48 // convert ASCII to integer
|
pos := int(r) - 48 // convert ASCII to integer
|
||||||
if pos > len(tokens) {
|
if pos > len(tokens) {
|
||||||
|
31
rl.go
31
rl.go
@ -13,9 +13,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type lineReader struct {
|
type lineReader struct {
|
||||||
rl *readline.Instance
|
rl *readline.Readline
|
||||||
fileHist *fileHistory
|
fileHist *fileHistory
|
||||||
}
|
}
|
||||||
|
|
||||||
var hinter *rt.Closure
|
var hinter *rt.Closure
|
||||||
var highlighter *rt.Closure
|
var highlighter *rt.Closure
|
||||||
|
|
||||||
@ -54,18 +55,24 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
|||||||
rl.ViModeCallback = func(mode readline.ViMode) {
|
rl.ViModeCallback = func(mode readline.ViMode) {
|
||||||
modeStr := ""
|
modeStr := ""
|
||||||
switch mode {
|
switch mode {
|
||||||
case readline.VimKeys: modeStr = "normal"
|
case readline.VimKeys:
|
||||||
case readline.VimInsert: modeStr = "insert"
|
modeStr = "normal"
|
||||||
case readline.VimDelete: modeStr = "delete"
|
case readline.VimInsert:
|
||||||
case readline.VimReplaceOnce, readline.VimReplaceMany: modeStr = "replace"
|
modeStr = "insert"
|
||||||
|
case readline.VimDelete:
|
||||||
|
modeStr = "delete"
|
||||||
|
case readline.VimReplaceOnce, readline.VimReplaceMany:
|
||||||
|
modeStr = "replace"
|
||||||
}
|
}
|
||||||
setVimMode(modeStr)
|
setVimMode(modeStr)
|
||||||
}
|
}
|
||||||
rl.ViActionCallback = func(action readline.ViAction, args []string) {
|
rl.ViActionCallback = func(action readline.ViAction, args []string) {
|
||||||
actionStr := ""
|
actionStr := ""
|
||||||
switch action {
|
switch action {
|
||||||
case readline.VimActionPaste: actionStr = "paste"
|
case readline.VimActionPaste:
|
||||||
case readline.VimActionYank: actionStr = "yank"
|
actionStr = "paste"
|
||||||
|
case readline.VimActionYank:
|
||||||
|
actionStr = "yank"
|
||||||
}
|
}
|
||||||
hooks.Emit("hilbish.vimAction", actionStr, args)
|
hooks.Emit("hilbish.vimAction", actionStr, args)
|
||||||
}
|
}
|
||||||
@ -188,8 +195,10 @@ func newLineReader(prompt string, noHist bool) *lineReader {
|
|||||||
|
|
||||||
var dispType readline.TabDisplayType
|
var dispType readline.TabDisplayType
|
||||||
switch luaCompType.AsString() {
|
switch luaCompType.AsString() {
|
||||||
case "grid": dispType = readline.TabDisplayGrid
|
case "grid":
|
||||||
case "list": dispType = readline.TabDisplayList
|
dispType = readline.TabDisplayGrid
|
||||||
|
case "list":
|
||||||
|
dispType = readline.TabDisplayList
|
||||||
// need special cases, will implement later
|
// need special cases, will implement later
|
||||||
//case "map": dispType = readline.TabDisplayMap
|
//case "map": dispType = readline.TabDisplayMap
|
||||||
}
|
}
|
||||||
@ -227,8 +236,8 @@ func (lr *lineReader) SetPrompt(p string) {
|
|||||||
halfPrompt := strings.Split(p, "\n")
|
halfPrompt := strings.Split(p, "\n")
|
||||||
if len(halfPrompt) > 1 {
|
if len(halfPrompt) > 1 {
|
||||||
lr.rl.Multiline = true
|
lr.rl.Multiline = true
|
||||||
lr.rl.SetPrompt(strings.Join(halfPrompt[:len(halfPrompt) - 1], "\n"))
|
lr.rl.SetPrompt(strings.Join(halfPrompt[:len(halfPrompt)-1], "\n"))
|
||||||
lr.rl.MultilinePrompt = halfPrompt[len(halfPrompt) - 1:][0]
|
lr.rl.MultilinePrompt = halfPrompt[len(halfPrompt)-1:][0]
|
||||||
} else {
|
} else {
|
||||||
lr.rl.Multiline = false
|
lr.rl.Multiline = false
|
||||||
lr.rl.MultilinePrompt = ""
|
lr.rl.MultilinePrompt = ""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user