Start work on kill ring
This commit is contained in:
parent
b7816d26be
commit
ea583f60b3
@ -51,6 +51,7 @@ func (self *Readline) all_text() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *Readline) add_text(text string) {
|
func (self *Readline) add_text(text string) {
|
||||||
|
defer func() { self.last_action = ActionAddText }()
|
||||||
new_lines := make([]string, 0, len(self.lines)+4)
|
new_lines := make([]string, 0, len(self.lines)+4)
|
||||||
new_lines = append(new_lines, self.lines[:self.cursor.Y]...)
|
new_lines = append(new_lines, self.lines[:self.cursor.Y]...)
|
||||||
var lines_after []string
|
var lines_after []string
|
||||||
@ -355,7 +356,37 @@ func (self *Readline) move_to_start_of_word(amt uint, traverse_line_breaks bool)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Readline) kill_text(text string) {
|
||||||
|
if ActionStartKillActions < self.last_action && self.last_action < ActionEndKillActions {
|
||||||
|
self.kill_ring.append_to_existing_item(text)
|
||||||
|
} else {
|
||||||
|
self.kill_ring.add_new_item(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Readline) kill_to_end_of_line() bool {
|
||||||
|
line := self.lines[self.cursor.Y]
|
||||||
|
if self.cursor.X >= len(line) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
self.lines[self.cursor.Y] = line[:self.cursor.X]
|
||||||
|
self.kill_text(line[self.cursor.X:])
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Readline) kill_to_start_of_line() bool {
|
||||||
|
line := self.lines[self.cursor.Y]
|
||||||
|
if self.cursor.X <= 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
self.lines[self.cursor.Y] = line[self.cursor.X:]
|
||||||
|
self.kill_text(line[:self.cursor.X])
|
||||||
|
self.cursor.X = 0
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Readline) perform_action(ac Action, repeat_count uint) error {
|
func (self *Readline) perform_action(ac Action, repeat_count uint) error {
|
||||||
|
defer func() { self.last_action = ac }()
|
||||||
switch ac {
|
switch ac {
|
||||||
case ActionBackspace:
|
case ActionBackspace:
|
||||||
if self.erase_chars_before_cursor(repeat_count, true) > 0 {
|
if self.erase_chars_before_cursor(repeat_count, true) > 0 {
|
||||||
@ -435,6 +466,14 @@ func (self *Readline) perform_action(ac Action, repeat_count uint) error {
|
|||||||
self.RedrawNonAtomic()
|
self.RedrawNonAtomic()
|
||||||
self.loop.EndAtomicUpdate()
|
self.loop.EndAtomicUpdate()
|
||||||
return nil
|
return nil
|
||||||
|
case ActionKillToEndOfLine:
|
||||||
|
if self.kill_to_end_of_line() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
case ActionKillToStartOfLine:
|
||||||
|
if self.kill_to_start_of_line() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ErrCouldNotPerformAction
|
return ErrCouldNotPerformAction
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
package readline
|
package readline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"container/list"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -56,8 +57,49 @@ const (
|
|||||||
ActionHistoryNext
|
ActionHistoryNext
|
||||||
ActionHistoryPrevious
|
ActionHistoryPrevious
|
||||||
ActionClearScreen
|
ActionClearScreen
|
||||||
|
ActionAddText
|
||||||
|
|
||||||
|
ActionStartKillActions
|
||||||
|
ActionKillToEndOfLine
|
||||||
|
ActionKillToStartOfLine
|
||||||
|
ActionEndKillActions
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type kill_ring struct {
|
||||||
|
items *list.List
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *kill_ring) append_to_existing_item(text string) {
|
||||||
|
e := self.items.Front()
|
||||||
|
if e == nil {
|
||||||
|
self.add_new_item(text)
|
||||||
|
}
|
||||||
|
e.Value = e.Value.(string) + text
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *kill_ring) add_new_item(text string) {
|
||||||
|
if text != "" {
|
||||||
|
self.items.PushFront(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *kill_ring) yank() string {
|
||||||
|
e := self.items.Front()
|
||||||
|
if e == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return e.Value.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *kill_ring) pop_yank() string {
|
||||||
|
e := self.items.Front()
|
||||||
|
if e == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
self.items.MoveToBack(e)
|
||||||
|
return self.yank()
|
||||||
|
}
|
||||||
|
|
||||||
type Readline struct {
|
type Readline struct {
|
||||||
prompt string
|
prompt string
|
||||||
prompt_len int
|
prompt_len int
|
||||||
@ -66,6 +108,7 @@ type Readline struct {
|
|||||||
mark_prompts bool
|
mark_prompts bool
|
||||||
loop *loop.Loop
|
loop *loop.Loop
|
||||||
history *History
|
history *History
|
||||||
|
kill_ring kill_ring
|
||||||
|
|
||||||
// The number of lines after the initial line on the screen
|
// The number of lines after the initial line on the screen
|
||||||
cursor_y int
|
cursor_y int
|
||||||
@ -75,6 +118,7 @@ type Readline struct {
|
|||||||
// The cursor position in the text
|
// The cursor position in the text
|
||||||
cursor Position
|
cursor Position
|
||||||
bracketed_paste_buffer strings.Builder
|
bracketed_paste_buffer strings.Builder
|
||||||
|
last_action Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(loop *loop.Loop, r RlInit) *Readline {
|
func New(loop *loop.Loop, r RlInit) *Readline {
|
||||||
@ -84,7 +128,7 @@ func New(loop *loop.Loop, r RlInit) *Readline {
|
|||||||
}
|
}
|
||||||
ans := &Readline{
|
ans := &Readline{
|
||||||
prompt: r.Prompt, prompt_len: wcswidth.Stringwidth(r.Prompt), mark_prompts: !r.DontMarkPrompts,
|
prompt: r.Prompt, prompt_len: wcswidth.Stringwidth(r.Prompt), mark_prompts: !r.DontMarkPrompts,
|
||||||
loop: loop, lines: []string{""}, history: NewHistory(r.HistoryPath, hc),
|
loop: loop, lines: []string{""}, history: NewHistory(r.HistoryPath, hc), kill_ring: kill_ring{items: list.New().Init()},
|
||||||
}
|
}
|
||||||
if r.ContinuationPrompt != "" || !r.EmptyContinuationPrompt {
|
if r.ContinuationPrompt != "" || !r.EmptyContinuationPrompt {
|
||||||
ans.continuation_prompt = r.ContinuationPrompt
|
ans.continuation_prompt = r.ContinuationPrompt
|
||||||
@ -112,6 +156,7 @@ func (self *Readline) ResetText() {
|
|||||||
self.lines = []string{""}
|
self.lines = []string{""}
|
||||||
self.cursor = Position{}
|
self.cursor = Position{}
|
||||||
self.cursor_y = 0
|
self.cursor_y = 0
|
||||||
|
self.last_action = ActionNil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *Readline) ChangeLoopAndResetText(lp *loop.Loop) {
|
func (self *Readline) ChangeLoopAndResetText(lp *loop.Loop) {
|
||||||
|
|||||||
@ -39,6 +39,10 @@ var default_shortcuts = map[string]Action{
|
|||||||
|
|
||||||
"ctrl+d": ActionEndInput,
|
"ctrl+d": ActionEndInput,
|
||||||
"enter": ActionAcceptInput,
|
"enter": ActionAcceptInput,
|
||||||
|
|
||||||
|
"ctrl+k": ActionKillToEndOfLine,
|
||||||
|
"ctrl+x": ActionKillToStartOfLine,
|
||||||
|
"ctrl+u": ActionKillToStartOfLine,
|
||||||
}
|
}
|
||||||
|
|
||||||
func action_for_key_event(event *loop.KeyEvent, shortcuts map[string]Action) Action {
|
func action_for_key_event(event *loop.KeyEvent, shortcuts map[string]Action) Action {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user