Check for readonly on viewtype and if true do not let any edits or paste to buffer. eg help and plugins. Finished needs checking. (#674)

* corrected spelling error and missing public function comments

* check for readonly and if true do not insert character

* mouse middle  click checks for view type readonly and does not paste if view is readonly

* check for view readonly with binding keys and if readonly do not change the content.
This commit is contained in:
Tommy 2017-05-29 19:18:10 +01:00 committed by Zachary Yedidia
parent 89863660ba
commit 4644a2b5cc
3 changed files with 61 additions and 33 deletions

View file

@ -11,11 +11,11 @@ import (
const (
// Opposite and undoing events must have opposite values
// TextEventInsert repreasents an insertion event
// TextEventInsert represents an insertion event
TextEventInsert = 1
// TextEventRemove represents a deletion event
TextEventRemove = -1
// TextEventReplace represents a replace event
TextEventReplace = 0
)
@ -117,7 +117,7 @@ func (eh *EventHandler) Remove(start, end Loc) {
eh.Execute(e)
}
// Multiple creates an multiple insertions executes them
// MultipleReplace creates an multiple insertions executes them
func (eh *EventHandler) MultipleReplace(deltas []Delta) {
e := &TextEvent{
C: eh.buf.Cursor,

View file

@ -267,11 +267,16 @@ func Abs(n int) int {
return n
}
// FuncName returns the name of a given function object
// FuncName returns the full name of a given function object
func FuncName(i interface{}) string {
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}
// ShortFuncName returns the name only of a given function object
func ShortFuncName(i interface{}) string {
return strings.TrimPrefix(runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name(), "main.(*View).")
}
// SplitCommandArgs separates multiple command arguments which may be quoted.
// The returned slice contains at least one string
func SplitCommandArgs(input string) []string {

View file

@ -462,6 +462,7 @@ func (v *View) HandleEvent(event tcell.Event) {
case *tcell.EventKey:
// Check first if input is a key binding, if it is we 'eat' the input and don't insert a rune
isBinding := false
readonlyBindingsList := []string{"Delete", "Insert", "Backspace", "Cut", "Play", "Paste", "Move", "Add", "DuplicateLine", "Macro"}
if e.Key() != tcell.KeyRune || e.Modifiers() != 0 {
for key, actions := range bindings {
if e.Key() == key.keyCode {
@ -474,11 +475,24 @@ func (v *View) HandleEvent(event tcell.Event) {
relocate = false
isBinding = true
for _, action := range actions {
relocate = action(v, true) || relocate
funcName := FuncName(action)
if funcName != "main.(*View).ToggleMacro" && funcName != "main.(*View).PlayMacro" {
if recordingMacro {
curMacro = append(curMacro, action)
readonlyBindingsResult := false
funcName := ShortFuncName(action)
if v.Type.readonly == true {
// check for readonly and if true only let key bindings get called if they do not change the contents.
for _, readonlyBindings := range readonlyBindingsList {
if strings.Contains(funcName, readonlyBindings) {
readonlyBindingsResult = true
}
}
}
if !readonlyBindingsResult {
// call the key binding
relocate = action(v, true) || relocate
// Macro
if funcName != "ToggleMacro" && funcName != "PlayMacro" {
if recordingMacro {
curMacro = append(curMacro, action)
}
}
}
}
@ -488,33 +502,39 @@ func (v *View) HandleEvent(event tcell.Event) {
}
}
if !isBinding && e.Key() == tcell.KeyRune {
// Insert a character
if v.Cursor.HasSelection() {
v.Cursor.DeleteSelection()
v.Cursor.ResetSelection()
}
v.Buf.Insert(v.Cursor.Loc, string(e.Rune()))
v.Cursor.Right()
for pl := range loadedPlugins {
_, err := Call(pl+".onRune", string(e.Rune()), v)
if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
TermMessage(err)
// Check viewtype if readonly don't insert a rune (readonly help and log view etc.)
if v.Type.readonly == false {
// Insert a character
if v.Cursor.HasSelection() {
v.Cursor.DeleteSelection()
v.Cursor.ResetSelection()
}
}
v.Buf.Insert(v.Cursor.Loc, string(e.Rune()))
v.Cursor.Right()
if recordingMacro {
curMacro = append(curMacro, e.Rune())
for pl := range loadedPlugins {
_, err := Call(pl+".onRune", string(e.Rune()), v)
if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
TermMessage(err)
}
}
if recordingMacro {
curMacro = append(curMacro, e.Rune())
}
}
}
case *tcell.EventPaste:
if !PreActionCall("Paste", v) {
break
// Check viewtype if readonly don't paste (readonly help and log view etc.)
if v.Type.readonly == false {
if !PreActionCall("Paste", v) {
break
}
v.paste(e.Text())
PostActionCall("Paste", v)
}
v.paste(e.Text())
PostActionCall("Paste", v)
case *tcell.EventMouse:
x, y := e.Position()
x -= v.lineNumOffset - v.leftCol + v.x
@ -571,9 +591,12 @@ func (v *View) HandleEvent(event tcell.Event) {
}
}
case tcell.Button2:
// Middle mouse button was clicked,
// We should paste primary
v.PastePrimary(true)
// Check viewtype if readonly don't paste (readonly help and log view etc.)
if v.Type.readonly == false {
// Middle mouse button was clicked,
// We should paste primary
v.PastePrimary(true)
}
case tcell.ButtonNone:
// Mouse event with no click
if !v.mouseReleased {