- err := v.Buf.Save()
- if err != nil {
- if strings.HasSuffix(err.Error(), "permission denied") {
- choice, _ := messenger.YesNoPrompt("Permission denied. Do you want to save this file using sudo? (y,n)")
- if choice {
- err = v.Buf.SaveWithSudo()
- if err != nil {
- messenger.Error(err.Error())
- return false
- }
- }
- messenger.Reset()
- messenger.Clear()
- } else {
- messenger.Error(err.Error())
- }
- } else {
- messenger.Message("Saved " + v.Buf.Path)
- }
- return false
-}
-
-// Find opens a prompt and searches forward for the input
-func (v *View) Find() bool {
- if v.Cursor.HasSelection() {
- searchStart = ToCharPos(v.Cursor.CurSelection[1], v.Buf)
- } else {
- searchStart = ToCharPos(v.Cursor.Loc, v.Buf)
- }
- BeginSearch()
- return true
-}
-
-// FindNext searches forwards for the last used search term
-func (v *View) FindNext() bool {
- if v.Cursor.HasSelection() {
- searchStart = ToCharPos(v.Cursor.CurSelection[1], v.Buf)
- } else {
- searchStart = ToCharPos(v.Cursor.Loc, v.Buf)
- }
- messenger.Message("Finding: " + lastSearch)
- Search(lastSearch, v, true)
- return true
-}
-
-// FindPrevious searches backwards for the last used search term
-func (v *View) FindPrevious() bool {
- if v.Cursor.HasSelection() {
- searchStart = ToCharPos(v.Cursor.CurSelection[0], v.Buf)
- } else {
- searchStart = ToCharPos(v.Cursor.Loc, v.Buf)
- }
- messenger.Message("Finding: " + lastSearch)
- Search(lastSearch, v, false)
- return true
-}
-
-// Undo undoes the last action
-func (v *View) Undo() bool {
- v.Buf.Undo()
- messenger.Message("Undid action")
- return true
-}
-
-// Redo redoes the last action
-func (v *View) Redo() bool {
- v.Buf.Redo()
- messenger.Message("Redid action")
- return true
-}
-
-// Copy the selection to the system clipboard
-func (v *View) Copy() bool {
- if v.Cursor.HasSelection() {
- clipboard.WriteAll(v.Cursor.GetSelection())
- v.freshClip = true
- messenger.Message("Copied selection")
- }
- return true
-}
-
-// CutLine cuts the current line to the clipboard
-func (v *View) CutLine() bool {
- v.Cursor.SelectLine()
- if !v.Cursor.HasSelection() {
- return false
- }
- if v.freshClip == true {
- if v.Cursor.HasSelection() {
- if clip, err := clipboard.ReadAll(); err != nil {
- messenger.Error(err)
- } else {
- clipboard.WriteAll(clip + v.Cursor.GetSelection())
- }
- }
- } else if time.Since(v.lastCutTime)/time.Second > 10*time.Second || v.freshClip == false {
- v.Copy()
- }
- v.freshClip = true
- v.lastCutTime = time.Now()
- v.Cursor.DeleteSelection()
- v.Cursor.ResetSelection()
- messenger.Message("Cut line")
- return true
-}
-
-// Cut the selection to the system clipboard
-func (v *View) Cut() bool {
- if v.Cursor.HasSelection() {
- clipboard.WriteAll(v.Cursor.GetSelection())
- v.Cursor.DeleteSelection()
- v.Cursor.ResetSelection()
- v.freshClip = true
- messenger.Message("Cut selection")
- }
- return true
-}
-
-// DuplicateLine duplicates the current line
-func (v *View) DuplicateLine() bool {
- v.Cursor.End()
- v.Buf.Insert(v.Cursor.Loc, "\n"+v.Buf.Line(v.Cursor.Y))
- v.Cursor.Right()
- messenger.Message("Duplicated line")
- return true
-}
-
-// Paste whatever is in the system clipboard into the buffer
-// Delete and paste if the user has a selection
-func (v *View) Paste() bool {
- if v.Cursor.HasSelection() {
- v.Cursor.DeleteSelection()
- v.Cursor.ResetSelection()
- }
- clip, _ := clipboard.ReadAll()
- v.Buf.Insert(v.Cursor.Loc, clip)
- v.Cursor.Loc = v.Cursor.Loc.Move(Count(clip), v.Buf)
- v.freshClip = false
- messenger.Message("Pasted clipboard")
- return true
-}
-
-// SelectAll selects the entire buffer
-func (v *View) SelectAll() bool {
- v.Cursor.CurSelection[0] = v.Buf.Start()
- v.Cursor.CurSelection[1] = v.Buf.End()
- // Put the cursor at the beginning
- v.Cursor.X = 0
- v.Cursor.Y = 0
- return true
-}
-
-// OpenFile opens a new file in the buffer
-func (v *View) OpenFile() bool {
- if v.CanClose("Continue? (yes, no, save) ") {
- filename, canceled := messenger.Prompt("File to open: ", "Open")
- if canceled {
- return true
- }
- home, _ := homedir.Dir()
- filename = strings.Replace(filename, "~", home, 1)
- file, err := ioutil.ReadFile(filename)
-
- if err != nil {
- messenger.Error(err.Error())
- return true
- }
- buf := NewBuffer(file, filename)
- v.OpenBuffer(buf)
- }
- return true
-}
-
-// Start moves the viewport to the start of the buffer
-func (v *View) Start() bool {
- v.Topline = 0
- return false
-}
-
-// End moves the viewport to the end of the buffer
-func (v *View) End() bool {
- if v.height > v.Buf.NumLines {
- v.Topline = 0
- } else {
- v.Topline = v.Buf.NumLines - v.height
- }
- return false
-}
-
-// PageUp scrolls the view up a page
-func (v *View) PageUp() bool {
- if v.Topline > v.height {
- v.ScrollUp(v.height)
- } else {
- v.Topline = 0
- }
- return false
-}
-
-// PageDown scrolls the view down a page
-func (v *View) PageDown() bool {
- if v.Buf.NumLines-(v.Topline+v.height) > v.height {
- v.ScrollDown(v.height)
- } else if v.Buf.NumLines >= v.height {
- v.Topline = v.Buf.NumLines - v.height
- }
- return false
-}
-
-// CursorPageUp places the cursor a page up
-func (v *View) CursorPageUp() bool {
- if v.Cursor.HasSelection() {
- v.Cursor.Loc = v.Cursor.CurSelection[0]
- v.Cursor.ResetSelection()
- }
- v.Cursor.UpN(v.height)
- return true
-}
-
-// CursorPageDown places the cursor a page up
-func (v *View) CursorPageDown() bool {
- if v.Cursor.HasSelection() {
- v.Cursor.Loc = v.Cursor.CurSelection[1]
- v.Cursor.ResetSelection()
- }
- v.Cursor.DownN(v.height)
- return true
-}
-
-// HalfPageUp scrolls the view up half a page
-func (v *View) HalfPageUp() bool {
- if v.Topline > v.height/2 {
- v.ScrollUp(v.height / 2)
- } else {
- v.Topline = 0
- }
- return false
-}
-
-// HalfPageDown scrolls the view down half a page
-func (v *View) HalfPageDown() bool {
- if v.Buf.NumLines-(v.Topline+v.height) > v.height/2 {
- v.ScrollDown(v.height / 2)
- } else {
- if v.Buf.NumLines >= v.height {
- v.Topline = v.Buf.NumLines - v.height
- }
- }
- return false
-}
-
-// ToggleRuler turns line numbers off and on
-func (v *View) ToggleRuler() bool {
- if settings["ruler"] == false {
- settings["ruler"] = true
- messenger.Message("Enabled ruler")
- } else {
- settings["ruler"] = false
- messenger.Message("Disabled ruler")
- }
- return false
-}
-
-// JumpLine jumps to a line and moves the view accordingly.
-func (v *View) JumpLine() bool {
- // Prompt for line number
- linestring, canceled := messenger.Prompt("Jump to line # ", "LineNumber")
- if canceled {
- return false
- }
- lineint, err := strconv.Atoi(linestring)
- lineint = lineint - 1 // fix offset
- if err != nil {
- messenger.Error(err) // return errors
- return false
- }
- // Move cursor and view if possible.
- if lineint < v.Buf.NumLines {
- v.Cursor.X = 0
- v.Cursor.Y = lineint
- return true
- }
- messenger.Error("Only ", v.Buf.NumLines, " lines to jump")
- return false
-}
-
-// ClearStatus clears the messenger bar
-func (v *View) ClearStatus() bool {
- messenger.Message("")
- return false
-}
-
-// ToggleHelp toggles the help screen
-func (v *View) ToggleHelp() bool {
- if !v.helpOpen {
- v.lastBuffer = v.Buf
- helpBuffer := NewBuffer([]byte(helpTxt), "help.md")
- helpBuffer.Name = "Help"
- v.helpOpen = true
- v.OpenBuffer(helpBuffer)
- } else {
- v.OpenBuffer(v.lastBuffer)
- v.helpOpen = false
- }
- return true
-}
-
-// ShellMode opens a terminal to run a shell command
-func (v *View) ShellMode() bool {
- input, canceled := messenger.Prompt("$ ", "Shell")
- if !canceled {
- // The true here is for openTerm to make the command interactive
- HandleShellCommand(input, true)
- }
- return false
-}
-
-// CommandMode lets the user enter a command
-func (v *View) CommandMode() bool {
- input, canceled := messenger.Prompt("> ", "Command")
- if !canceled {
- HandleCommand(input)
- }
- return false
-}
-
-// Quit quits the editor
-// This behavior needs to be changed and should really only quit the editor if this
-// is the last view
-// However, since micro only supports one view for now, it doesn't really matter
-func (v *View) Quit() bool {
- if v.helpOpen {
- return v.ToggleHelp()
- }
- // Make sure not to quit if there are unsaved changes
- if views[mainView].CanClose("Quit anyway? (yes, no, save) ") {
- views[mainView].CloseBuffer()
- screen.Fini()
- os.Exit(0)
- }
- return false
-}
-
-// None is no action
-func None() bool {
- return false