X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=cmd%2Fmicro%2Fview.go;h=11f7e0cf7748e62598a3c48688d2afbf9712fad4;hb=be56918174be41c5cc8dce87bf3f8373b25f325b;hp=6cf2aaba20cbba4372d1c9470d6e55db82888e67;hpb=9530d6ad2047ab299dcece67483f468dbdc7bd17;p=micro.git diff --git a/cmd/micro/view.go b/cmd/micro/view.go index 6cf2aaba..11f7e0cf 100644 --- a/cmd/micro/view.go +++ b/cmd/micro/view.go @@ -11,15 +11,16 @@ import ( ) type ViewType struct { + kind int readonly bool // The file cannot be edited scratch bool // The file cannot be saved } var ( - vtDefault = ViewType{false, false} - vtHelp = ViewType{true, true} - vtLog = ViewType{true, true} - vtScratch = ViewType{false, true} + vtDefault = ViewType{0, false, false} + vtHelp = ViewType{1, true, true} + vtLog = ViewType{2, true, true} + vtScratch = ViewType{3, false, true} ) // The View struct stores information about a view into a buffer. @@ -198,18 +199,19 @@ func (v *View) ScrollDown(n int) { // causing them to lose the unsaved changes func (v *View) CanClose() bool { if v.Type == vtDefault && v.Buf.IsModified { - var char rune + var choice bool var canceled bool if v.Buf.Settings["autosave"].(bool) { - char = 'y' + choice = true } else { - char, canceled = messenger.LetterPrompt("Save changes to "+v.Buf.GetName()+" before closing? (y,n,esc) ", 'y', 'n') + choice, canceled = messenger.YesNoPrompt("Save changes to " + v.Buf.GetName() + " before closing? (y,n,esc) ") } if !canceled { - if char == 'y' { + //if char == 'y' { + if choice { v.Save(true) return true - } else if char == 'n' { + } else { return true } } @@ -257,9 +259,9 @@ func (v *View) Open(filename string) { if err != nil { messenger.Message(err.Error()) // File does not exist -- create an empty buffer with that name - buf = NewBuffer(strings.NewReader(""), filename) + buf = NewBufferFromString("", filename) } else { - buf = NewBuffer(file, filename) + buf = NewBuffer(file, FSize(file), filename) } v.OpenBuffer(buf) } @@ -460,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 { @@ -472,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) + } } } } @@ -486,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() + // 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() - 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) + 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()) + 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()) + v.paste(e.Text()) - PostActionCall("Paste", v) + PostActionCall("Paste", v) + } case *tcell.EventMouse: x, y := e.Position() x -= v.lineNumOffset - v.leftCol + v.x @@ -569,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 { @@ -648,7 +673,7 @@ func (v *View) openHelp(helpPage string) { if data, err := FindRuntimeFile(RTHelp, helpPage).Data(); err != nil { TermMessage("Unable to load help text", helpPage, "\n", err) } else { - helpBuffer := NewBuffer(strings.NewReader(string(data)), helpPage+".md") + helpBuffer := NewBufferFromString(string(data), helpPage+".md") helpBuffer.name = "Help" if v.Type == vtHelp { @@ -661,6 +686,10 @@ func (v *View) openHelp(helpPage string) { } func (v *View) DisplayView() { + if v.Buf.Settings["softwrap"].(bool) && v.leftCol != 0 { + v.leftCol = 0 + } + if v.Type == vtLog { // Log views should always follow the cursor... v.Relocate() @@ -688,9 +717,11 @@ func (v *View) DisplayView() { v.lineNumOffset += 2 } + divider := 0 if v.x != 0 { // One space for the extra split divider v.lineNumOffset++ + divider = 1 } xOffset := v.x + v.lineNumOffset @@ -723,6 +754,14 @@ func (v *View) DisplayView() { realLineN++ } + colorcolumn := int(v.Buf.Settings["colorcolumn"].(float64)) + if colorcolumn != 0 { + style := GetColor("color-column") + fg, _, _ := style.Decompose() + st := defStyle.Background(fg) + screen.SetContent(xOffset+colorcolumn, yOffset+visualLineN, ' ', nil, st) + } + screenX = v.x // If there are gutter messages we need to display the '>>' symbol here @@ -788,25 +827,25 @@ func (v *View) DisplayView() { // Write the spaces before the line number if necessary for i := 0; i < maxLineNumLength-len(lineNum); i++ { - screen.SetContent(screenX, yOffset+visualLineN, ' ', nil, lineNumStyle) + screen.SetContent(screenX+divider, yOffset+visualLineN, ' ', nil, lineNumStyle) screenX++ } if softwrapped && visualLineN != 0 { // Pad without the line number because it was written on the visual line before for range lineNum { - screen.SetContent(screenX, yOffset+visualLineN, ' ', nil, lineNumStyle) + screen.SetContent(screenX+divider, yOffset+visualLineN, ' ', nil, lineNumStyle) screenX++ } } else { // Write the actual line number for _, ch := range lineNum { - screen.SetContent(screenX, yOffset+visualLineN, ch, nil, lineNumStyle) + screen.SetContent(screenX+divider, yOffset+visualLineN, ch, nil, lineNumStyle) screenX++ } } // Write the extra space - screen.SetContent(screenX, yOffset+visualLineN, ' ', nil, lineNumStyle) + screen.SetContent(screenX+divider, yOffset+visualLineN, ' ', nil, lineNumStyle) screenX++ } @@ -816,6 +855,13 @@ func (v *View) DisplayView() { if char != nil { lineStyle := char.style + colorcolumn := int(v.Buf.Settings["colorcolumn"].(float64)) + if colorcolumn != 0 && char.visualLoc.X == colorcolumn { + style := GetColor("color-column") + fg, _, _ := style.Decompose() + lineStyle = lineStyle.Background(fg) + } + charLoc := char.realLoc if v.Cursor.HasSelection() && (charLoc.GreaterEqual(v.Cursor.CurSelection[0]) && charLoc.LessThan(v.Cursor.CurSelection[1]) || @@ -896,28 +942,25 @@ func (v *View) DisplayView() { } } - if v.x != 0 && visualLineN < v.Height { + if divider != 0 { dividerStyle := defStyle if style, ok := colorscheme["divider"]; ok { dividerStyle = style } - for i := visualLineN + 1; i < v.Height; i++ { + for i := 0; i < v.Height; i++ { screen.SetContent(v.x, yOffset+i, '|', nil, dividerStyle.Reverse(true)) } } } -// DisplayCursor draws the current buffer's cursor to the screen -func (v *View) DisplayCursor(x, y int) { - // screen.ShowCursor(v.x+v.Cursor.GetVisualX()+v.lineNumOffset-v.leftCol, y) - screen.ShowCursor(x, y) -} - // Display renders the view, the cursor, and statusline func (v *View) Display() { + if globalSettings["termtitle"].(bool) { + screen.SetTitle("micro: " + v.Buf.GetName()) + } v.DisplayView() // Don't draw the cursor if it is out of the viewport or if it has a selection - if (v.Cursor.Y-v.Topline < 0 || v.Cursor.Y-v.Topline > v.Height-1) || v.Cursor.HasSelection() { + if v.Num == tabs[curTab].CurView && (v.Cursor.Y-v.Topline < 0 || v.Cursor.Y-v.Topline > v.Height-1 || v.Cursor.HasSelection()) { screen.HideCursor() } _, screenH := screen.Size()