Regular Expressions 101

Save & Share

Flavor

  • PCRE2 (PHP >=7.3)
  • PCRE (PHP <7.3)
  • ECMAScript (JavaScript)
  • Python
  • Golang
  • Java 8
  • .NET 7.0 (C#)
  • Rust
  • Regex Flavor Guide

Function

  • Match
  • Substitution
  • List
  • Unit Tests

Tools

Sponsors
There are currently no sponsors. Become a sponsor today!
An explanation of your regex will be automatically generated as you type.
Detailed match information will be displayed here automatically.
  • All Tokens
  • Common Tokens
  • General Tokens
  • Anchors
  • Meta Sequences
  • Quantifiers
  • Group Constructs
  • Character Classes
  • Flags/Modifiers
  • Substitution
  • A single character of: a, b or c
    [abc]
  • A character except: a, b or c
    [^abc]
  • A character in the range: a-z
    [a-z]
  • A character not in the range: a-z
    [^a-z]
  • A character in the range: a-z or A-Z
    [a-zA-Z]
  • Any single character
    .
  • Alternate - match either a or b
    a|b
  • Any whitespace character
    \s
  • Any non-whitespace character
    \S
  • Any digit
    \d
  • Any non-digit
    \D
  • Any word character
    \w
  • Any non-word character
    \W
  • Non-capturing group
    (?:...)
  • Capturing group
    (...)
  • Zero or one of a
    a?
  • Zero or more of a
    a*
  • One or more of a
    a+
  • Exactly 3 of a
    a{3}
  • 3 or more of a
    a{3,}
  • Between 3 and 6 of a
    a{3,6}
  • Start of string
    ^
  • End of string
    $
  • A word boundary
    \b
  • Non-word boundary
    \B

Regular Expression

/
/
gm

Test String

Substitution

Processing...

Code Generator

Generated Code

#include <MsgBoxConstants.au3> ; to declare the Constants of MsgBox Local $sRegex = "(?m)(?x)" & @CRLF & _ "" & @CRLF & _ "# Set intent level" & @CRLF & _ "(?(DEFINE)(?<indent>[[:space:]]{4}))" & @CRLF & _ "" & @CRLF & _ "# Must start at new line" & @CRLF & _ "^" & @CRLF & _ "# Captures following statement's description comment lines if written" & @CRLF & _ "(?<statementDescComment> " & @CRLF & _ " (?: " & @CRLF & _ " # Repeat below until next line not comment" & @CRLF & _ " (?=(?P>indent)\/)\V*\v" & @CRLF & _ " )+" & @CRLF & _ ")?" & @CRLF & _ "# Generic Statement Capture" & @CRLF & _ "(?<statement>" & @CRLF & _ "# Const declaration capture" & @CRLF & _ "(?<const>" & @CRLF & _ " (?P>indent)const[[:space:]]*\([[:space:]]*" & @CRLF & _ " \v" & @CRLF & _ " (?:" & @CRLF & _ " (?!(?P>indent)\))\V*\v" & @CRLF & _ " )*" & @CRLF & _ " (?P>indent)\)" & @CRLF & _ ")" & @CRLF & _ "|" & @CRLF & _ "# Full function declaration capture" & @CRLF & _ "(?<func>" & @CRLF & _ " # Function declaration initialization" & @CRLF & _ " (?<funcDecLine>" & @CRLF & _ " (?P>indent)func\V+" & @CRLF & _ " )\v" & @CRLF & _ " # Repeat subcapture until line starting with close bracket" & @CRLF & _ " (?:" & @CRLF & _ " (?!(?P>indent)\})\V*\v" & @CRLF & _ " )*" & @CRLF & _ " # Closing bracket" & @CRLF & _ " (?<funcCloseBracket>(?P>indent)\})" & @CRLF & _ ")" & @CRLF & _ "|" & @CRLF & _ "(?<type>" & @CRLF & _ " # Type Declaration" & @CRLF & _ "" & @CRLF & _ " # Check before wasting time" & @CRLF & _ " (?=(?P>indent)type)" & @CRLF & _ "" & @CRLF & _ " # Short Form" & @CRLF & _ " (?<typeDecShort>" & @CRLF & _ " (?P>indent)type\V+[^\{]\v" & @CRLF & _ " )" & @CRLF & _ " |" & @CRLF & _ " # Longer Form (Brackted)" & @CRLF & _ " (?<typeDecLong>" & @CRLF & _ " (?P>indent)type\V+" & @CRLF & _ " )\v" & @CRLF & _ " # Repeat subcapture until line starting with close bracket" & @CRLF & _ " (?:" & @CRLF & _ " (?!(?P>indent)\})\V*\v" & @CRLF & _ " )*" & @CRLF & _ " # Closing bracket" & @CRLF & _ " (?<typeCloseBracket>(?P>indent)\})" & @CRLF & _ " )" & @CRLF & _ ")" Local $sString = " package main" & @CRLF & _ "" & @CRLF & _ " import (" & @CRLF & _ " "fmt"" & @CRLF & _ " "os"" & @CRLF & _ " "regexp"" & @CRLF & _ " "strconv"" & @CRLF & _ " "strings"" & @CRLF & _ " "time"" & @CRLF & _ " "unicode/utf8"" & @CRLF & _ "" & @CRLF & _ " "github.com/yuin/gopher-lua"" & @CRLF & _ " "github.com/zyedidia/clipboard"" & @CRLF & _ " "github.com/zyedidia/micro/cmd/micro/shellwords"" & @CRLF & _ " "github.com/zyedidia/tcell"" & @CRLF & _ " )" & @CRLF & _ "" & @CRLF & _ " // PreActionCall executes the lua pre callback if possible" & @CRLF & _ " func PreActionCall(funcName string, view *View, args ...interface{}) bool {" & @CRLF & _ " executeAction := true" & @CRLF & _ " for pl := range loadedPlugins {" & @CRLF & _ " ret, err := Call(pl+".pre"+funcName, append([]interface{}{view}, args...)...)" & @CRLF & _ " if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {" & @CRLF & _ " TermMessage(err)" & @CRLF & _ " continue" & @CRLF & _ " }" & @CRLF & _ " if ret == lua.LFalse {" & @CRLF & _ " executeAction = false" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return executeAction" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // PostActionCall executes the lua plugin callback if possible" & @CRLF & _ " func PostActionCall(funcName string, view *View, args ...interface{}) bool {" & @CRLF & _ " relocate := true" & @CRLF & _ " for pl := range loadedPlugins {" & @CRLF & _ " ret, err := Call(pl+".on"+funcName, append([]interface{}{view}, args...)...)" & @CRLF & _ " if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {" & @CRLF & _ " TermMessage(err)" & @CRLF & _ " continue" & @CRLF & _ " }" & @CRLF & _ " if ret == lua.LFalse {" & @CRLF & _ " relocate = false" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return relocate" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " func (v *View) deselect(index int) bool {" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.Loc = v.Cursor.CurSelection[index]" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " v.Cursor.StoreVisualX()" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // MousePress is the event that should happen when a normal click happens" & @CRLF & _ " // This is almost always bound to left click" & @CRLF & _ " func (v *View) MousePress(usePlugin bool, e *tcell.EventMouse) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("MousePress", v, e) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " x, y := e.Position()" & @CRLF & _ " x -= v.lineNumOffset - v.leftCol + v.x" & @CRLF & _ " y += v.Topline - v.y" & @CRLF & _ "" & @CRLF & _ " // This is usually bound to left click" & @CRLF & _ " v.MoveToMouseClick(x, y)" & @CRLF & _ " if v.mouseReleased {" & @CRLF & _ " if len(v.Buf.cursors) > 1 {" & @CRLF & _ " for i := 1; i < len(v.Buf.cursors); i++ {" & @CRLF & _ " v.Buf.cursors[i] = nil" & @CRLF & _ " }" & @CRLF & _ " v.Buf.cursors = v.Buf.cursors[:1]" & @CRLF & _ " v.Buf.UpdateCursors()" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " v.Relocate()" & @CRLF & _ " }" & @CRLF & _ " if time.Since(v.lastClickTime)/time.Millisecond < doubleClickThreshold && (x == v.lastLoc.X && y == v.lastLoc.Y) {" & @CRLF & _ " if v.doubleClick {" & @CRLF & _ " // Triple click" & @CRLF & _ " v.lastClickTime = time.Now()" & @CRLF & _ "" & @CRLF & _ " v.tripleClick = true" & @CRLF & _ " v.doubleClick = false" & @CRLF & _ "" & @CRLF & _ " v.Cursor.SelectLine()" & @CRLF & _ " v.Cursor.CopySelection("primary")" & @CRLF & _ " } else {" & @CRLF & _ " // Double click" & @CRLF & _ " v.lastClickTime = time.Now()" & @CRLF & _ "" & @CRLF & _ " v.doubleClick = true" & @CRLF & _ " v.tripleClick = false" & @CRLF & _ "" & @CRLF & _ " v.Cursor.SelectWord()" & @CRLF & _ " v.Cursor.CopySelection("primary")" & @CRLF & _ " }" & @CRLF & _ " } else {" & @CRLF & _ " v.doubleClick = false" & @CRLF & _ " v.tripleClick = false" & @CRLF & _ " v.lastClickTime = time.Now()" & @CRLF & _ "" & @CRLF & _ " v.Cursor.OrigSelection[0] = v.Cursor.Loc" & @CRLF & _ " v.Cursor.CurSelection[0] = v.Cursor.Loc" & @CRLF & _ " v.Cursor.CurSelection[1] = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " v.mouseReleased = false" & @CRLF & _ " } else if !v.mouseReleased {" & @CRLF & _ " if v.tripleClick {" & @CRLF & _ " v.Cursor.AddLineToSelection()" & @CRLF & _ " } else if v.doubleClick {" & @CRLF & _ " v.Cursor.AddWordToSelection()" & @CRLF & _ " } else {" & @CRLF & _ " v.Cursor.SetSelectionEnd(v.Cursor.Loc)" & @CRLF & _ " v.Cursor.CopySelection("primary")" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.lastLoc = Loc{x, y}" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " PostActionCall("MousePress", v, e)" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // ScrollUpAction scrolls the view up" & @CRLF & _ " func (v *View) ScrollUpAction(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("ScrollUp", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " scrollspeed := int(v.Buf.Settings["scrollspeed"].(float64))" & @CRLF & _ " v.ScrollUp(scrollspeed)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " PostActionCall("ScrollUp", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // ScrollDownAction scrolls the view up" & @CRLF & _ " func (v *View) ScrollDownAction(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("ScrollDown", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " scrollspeed := int(v.Buf.Settings["scrollspeed"].(float64))" & @CRLF & _ " v.ScrollDown(scrollspeed)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " PostActionCall("ScrollDown", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Center centers the view on the cursor" & @CRLF & _ " func (v *View) Center(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("Center", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Topline = v.Cursor.Y - v.Height/2" & @CRLF & _ " if v.Topline+v.Height > v.Buf.NumLines {" & @CRLF & _ " v.Topline = v.Buf.NumLines - v.Height" & @CRLF & _ " }" & @CRLF & _ " if v.Topline < 0 {" & @CRLF & _ " v.Topline = 0" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Center", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // CursorUp moves the cursor up" & @CRLF & _ " func (v *View) CursorUp(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("CursorUp", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.deselect(0)" & @CRLF & _ " v.Cursor.Up()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("CursorUp", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // CursorDown moves the cursor down" & @CRLF & _ " func (v *View) CursorDown(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("CursorDown", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.deselect(1)" & @CRLF & _ " v.Cursor.Down()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("CursorDown", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // CursorLeft moves the cursor left" & @CRLF & _ " func (v *View) CursorLeft(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("CursorLeft", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.Loc = v.Cursor.CurSelection[0]" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " v.Cursor.StoreVisualX()" & @CRLF & _ " } else {" & @CRLF & _ " tabstospaces := v.Buf.Settings["tabstospaces"].(bool)" & @CRLF & _ " tabmovement := v.Buf.Settings["tabmovement"].(bool)" & @CRLF & _ " if tabstospaces && tabmovement {" & @CRLF & _ " tabsize := int(v.Buf.Settings["tabsize"].(float64))" & @CRLF & _ " line := v.Buf.Line(v.Cursor.Y)" & @CRLF & _ " if v.Cursor.X-tabsize >= 0 && line[v.Cursor.X-tabsize:v.Cursor.X] == Spaces(tabsize) && IsStrWhitespace(line[0:v.Cursor.X-tabsize]) {" & @CRLF & _ " for i := 0; i < tabsize; i++ {" & @CRLF & _ " v.Cursor.Left()" & @CRLF & _ " }" & @CRLF & _ " } else {" & @CRLF & _ " v.Cursor.Left()" & @CRLF & _ " }" & @CRLF & _ " } else {" & @CRLF & _ " v.Cursor.Left()" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("CursorLeft", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // CursorRight moves the cursor right" & @CRLF & _ " func (v *View) CursorRight(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("CursorRight", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.Loc = v.Cursor.CurSelection[1]" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " v.Cursor.StoreVisualX()" & @CRLF & _ " } else {" & @CRLF & _ " tabstospaces := v.Buf.Settings["tabstospaces"].(bool)" & @CRLF & _ " tabmovement := v.Buf.Settings["tabmovement"].(bool)" & @CRLF & _ " if tabstospaces && tabmovement {" & @CRLF & _ " tabsize := int(v.Buf.Settings["tabsize"].(float64))" & @CRLF & _ " line := v.Buf.Line(v.Cursor.Y)" & @CRLF & _ " if v.Cursor.X+tabsize < Count(line) && line[v.Cursor.X:v.Cursor.X+tabsize] == Spaces(tabsize) && IsStrWhitespace(line[0:v.Cursor.X]) {" & @CRLF & _ " for i := 0; i < tabsize; i++ {" & @CRLF & _ " v.Cursor.Right()" & @CRLF & _ " }" & @CRLF & _ " } else {" & @CRLF & _ " v.Cursor.Right()" & @CRLF & _ " }" & @CRLF & _ " } else {" & @CRLF & _ " v.Cursor.Right()" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("CursorRight", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // WordRight moves the cursor one word to the right" & @CRLF & _ " func (v *View) WordRight(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("WordRight", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Cursor.WordRight()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("WordRight", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // WordLeft moves the cursor one word to the left" & @CRLF & _ " func (v *View) WordLeft(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("WordLeft", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Cursor.WordLeft()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("WordLeft", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectUp selects up one line" & @CRLF & _ " func (v *View) SelectUp(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectUp", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.OrigSelection[0] = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.Up()" & @CRLF & _ " v.Cursor.SelectTo(v.Cursor.Loc)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectUp", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectDown selects down one line" & @CRLF & _ " func (v *View) SelectDown(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectDown", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.OrigSelection[0] = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.Down()" & @CRLF & _ " v.Cursor.SelectTo(v.Cursor.Loc)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectDown", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectLeft selects the character to the left of the cursor" & @CRLF & _ " func (v *View) SelectLeft(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectLeft", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " loc := v.Cursor.Loc" & @CRLF & _ " count := v.Buf.End()" & @CRLF & _ " if loc.GreaterThan(count) {" & @CRLF & _ " loc = count" & @CRLF & _ " }" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.OrigSelection[0] = loc" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.Left()" & @CRLF & _ " v.Cursor.SelectTo(v.Cursor.Loc)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectLeft", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectRight selects the character to the right of the cursor" & @CRLF & _ " func (v *View) SelectRight(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectRight", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " loc := v.Cursor.Loc" & @CRLF & _ " count := v.Buf.End()" & @CRLF & _ " if loc.GreaterThan(count) {" & @CRLF & _ " loc = count" & @CRLF & _ " }" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.OrigSelection[0] = loc" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.Right()" & @CRLF & _ " v.Cursor.SelectTo(v.Cursor.Loc)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectRight", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectWordRight selects the word to the right of the cursor" & @CRLF & _ " func (v *View) SelectWordRight(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectWordRight", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.OrigSelection[0] = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.WordRight()" & @CRLF & _ " v.Cursor.SelectTo(v.Cursor.Loc)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectWordRight", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectWordLeft selects the word to the left of the cursor" & @CRLF & _ " func (v *View) SelectWordLeft(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectWordLeft", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.OrigSelection[0] = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.WordLeft()" & @CRLF & _ " v.Cursor.SelectTo(v.Cursor.Loc)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectWordLeft", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // StartOfLine moves the cursor to the start of the line" & @CRLF & _ " func (v *View) StartOfLine(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("StartOfLine", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.deselect(0)" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.X != 0 {" & @CRLF & _ " v.Cursor.Start()" & @CRLF & _ " } else {" & @CRLF & _ " v.Cursor.StartOfText()" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("StartOfLine", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // EndOfLine moves the cursor to the end of the line" & @CRLF & _ " func (v *View) EndOfLine(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("EndOfLine", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.deselect(0)" & @CRLF & _ "" & @CRLF & _ " v.Cursor.End()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("EndOfLine", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectLine selects the entire current line" & @CRLF & _ " func (v *View) SelectLine(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectLine", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Cursor.SelectLine()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectLine", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectToStartOfLine selects to the start of the current line" & @CRLF & _ " func (v *View) SelectToStartOfLine(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectToStartOfLine", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.OrigSelection[0] = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.Start()" & @CRLF & _ " v.Cursor.SelectTo(v.Cursor.Loc)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectToStartOfLine", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectToEndOfLine selects to the end of the current line" & @CRLF & _ " func (v *View) SelectToEndOfLine(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectToEndOfLine", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.OrigSelection[0] = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.End()" & @CRLF & _ " v.Cursor.SelectTo(v.Cursor.Loc)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectToEndOfLine", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // ParagraphPrevious moves the cursor to the previous empty line, or beginning of the buffer if there's none" & @CRLF & _ " func (v *View) ParagraphPrevious(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("ParagraphPrevious", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ " var line int" & @CRLF & _ " for line = v.Cursor.Y; line > 0; line-- {" & @CRLF & _ " if len(v.Buf.lines[line].data) == 0 && line != v.Cursor.Y {" & @CRLF & _ " v.Cursor.X = 0" & @CRLF & _ " v.Cursor.Y = line" & @CRLF & _ " break" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " // If no empty line found. move cursor to end of buffer" & @CRLF & _ " if line == 0 {" & @CRLF & _ " v.Cursor.Loc = v.Buf.Start()" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("ParagraphPrevious", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // ParagraphNext moves the cursor to the next empty line, or end of the buffer if there's none" & @CRLF & _ " func (v *View) ParagraphNext(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("ParagraphNext", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " var line int" & @CRLF & _ " for line = v.Cursor.Y; line < len(v.Buf.lines); line++ {" & @CRLF & _ " if len(v.Buf.lines[line].data) == 0 && line != v.Cursor.Y {" & @CRLF & _ " v.Cursor.X = 0" & @CRLF & _ " v.Cursor.Y = line" & @CRLF & _ " break" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " // If no empty line found. move cursor to end of buffer" & @CRLF & _ " if line == len(v.Buf.lines) {" & @CRLF & _ " v.Cursor.Loc = v.Buf.End()" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("ParagraphNext", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Retab changes all tabs to spaces or all spaces to tabs depending" & @CRLF & _ " // on the user's settings" & @CRLF & _ " func (v *View) Retab(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("Retab", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " toSpaces := v.Buf.Settings["tabstospaces"].(bool)" & @CRLF & _ " tabsize := int(v.Buf.Settings["tabsize"].(float64))" & @CRLF & _ " dirty := false" & @CRLF & _ "" & @CRLF & _ " for i := 0; i < v.Buf.NumLines; i++ {" & @CRLF & _ " l := v.Buf.Line(i)" & @CRLF & _ "" & @CRLF & _ " ws := GetLeadingWhitespace(l)" & @CRLF & _ " if ws != "" {" & @CRLF & _ " if toSpaces {" & @CRLF & _ " ws = strings.Replace(ws, "\t", Spaces(tabsize), -1)" & @CRLF & _ " } else {" & @CRLF & _ " ws = strings.Replace(ws, Spaces(tabsize), "\t", -1)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " l = strings.TrimLeft(l, " \t")" & @CRLF & _ " v.Buf.lines[i].data = []byte(ws + l)" & @CRLF & _ " dirty = true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Buf.IsModified = dirty" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Retab", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // CursorStart moves the cursor to the start of the buffer" & @CRLF & _ " func (v *View) CursorStart(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("CursorStart", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.deselect(0)" & @CRLF & _ "" & @CRLF & _ " v.Cursor.X = 0" & @CRLF & _ " v.Cursor.Y = 0" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("CursorStart", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // CursorEnd moves the cursor to the end of the buffer" & @CRLF & _ " func (v *View) CursorEnd(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("CursorEnd", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.deselect(0)" & @CRLF & _ "" & @CRLF & _ " v.Cursor.Loc = v.Buf.End()" & @CRLF & _ " v.Cursor.StoreVisualX()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("CursorEnd", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectToStart selects the text from the cursor to the start of the buffer" & @CRLF & _ " func (v *View) SelectToStart(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectToStart", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.OrigSelection[0] = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " v.CursorStart(false)" & @CRLF & _ " v.Cursor.SelectTo(v.Buf.Start())" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectToStart", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectToEnd selects the text from the cursor to the end of the buffer" & @CRLF & _ " func (v *View) SelectToEnd(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectToEnd", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.OrigSelection[0] = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " v.CursorEnd(false)" & @CRLF & _ " v.Cursor.SelectTo(v.Buf.End())" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectToEnd", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // InsertSpace inserts a space" & @CRLF & _ " func (v *View) InsertSpace(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("InsertSpace", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.DeleteSelection()" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " }" & @CRLF & _ " v.Buf.Insert(v.Cursor.Loc, " ")" & @CRLF & _ " // v.Cursor.Right()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("InsertSpace", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // InsertNewline inserts a newline plus possible some whitespace if autoindent is on" & @CRLF & _ " func (v *View) InsertNewline(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("InsertNewline", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Insert a newline" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.DeleteSelection()" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " ws := GetLeadingWhitespace(v.Buf.Line(v.Cursor.Y))" & @CRLF & _ " cx := v.Cursor.X" & @CRLF & _ " v.Buf.Insert(v.Cursor.Loc, "\n")" & @CRLF & _ " // v.Cursor.Right()" & @CRLF & _ "" & @CRLF & _ " if v.Buf.Settings["autoindent"].(bool) {" & @CRLF & _ " if cx < len(ws) {" & @CRLF & _ " ws = ws[0:cx]" & @CRLF & _ " }" & @CRLF & _ " v.Buf.Insert(v.Cursor.Loc, ws)" & @CRLF & _ " // for i := 0; i < len(ws); i++ {" & @CRLF & _ " // v.Cursor.Right()" & @CRLF & _ " // }" & @CRLF & _ "" & @CRLF & _ " // Remove the whitespaces if keepautoindent setting is off" & @CRLF & _ " if IsSpacesOrTabs(v.Buf.Line(v.Cursor.Y-1)) && !v.Buf.Settings["keepautoindent"].(bool) {" & @CRLF & _ " line := v.Buf.Line(v.Cursor.Y - 1)" & @CRLF & _ " v.Buf.Remove(Loc{0, v.Cursor.Y - 1}, Loc{Count(line), v.Cursor.Y - 1})" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.LastVisualX = v.Cursor.GetVisualX()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("InsertNewline", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Backspace deletes the previous character" & @CRLF & _ " func (v *View) Backspace(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("Backspace", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Delete a character" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.DeleteSelection()" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " } else if v.Cursor.Loc.GreaterThan(v.Buf.Start()) {" & @CRLF & _ " // We have to do something a bit hacky here because we want to" & @CRLF & _ " // delete the line by first moving left and then deleting backwards" & @CRLF & _ " // but the undo redo would place the cursor in the wrong place" & @CRLF & _ " // So instead we move left, save the position, move back, delete" & @CRLF & _ " // and restore the position" & @CRLF & _ "" & @CRLF & _ " // If the user is using spaces instead of tabs and they are deleting" & @CRLF & _ " // whitespace at the start of the line, we should delete as if it's a" & @CRLF & _ " // tab (tabSize number of spaces)" & @CRLF & _ " lineStart := sliceEnd(v.Buf.LineBytes(v.Cursor.Y), v.Cursor.X)" & @CRLF & _ " tabSize := int(v.Buf.Settings["tabsize"].(float64))" & @CRLF & _ " if v.Buf.Settings["tabstospaces"].(bool) && IsSpaces(lineStart) && utf8.RuneCount(lineStart) != 0 && utf8.RuneCount(lineStart)%tabSize == 0 {" & @CRLF & _ " loc := v.Cursor.Loc" & @CRLF & _ " v.Buf.Remove(loc.Move(-tabSize, v.Buf), loc)" & @CRLF & _ " } else {" & @CRLF & _ " loc := v.Cursor.Loc" & @CRLF & _ " v.Buf.Remove(loc.Move(-1, v.Buf), loc)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.LastVisualX = v.Cursor.GetVisualX()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Backspace", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // DeleteWordRight deletes the word to the right of the cursor" & @CRLF & _ " func (v *View) DeleteWordRight(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("DeleteWordRight", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.SelectWordRight(false)" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.DeleteSelection()" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("DeleteWordRight", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // DeleteWordLeft deletes the word to the left of the cursor" & @CRLF & _ " func (v *View) DeleteWordLeft(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("DeleteWordLeft", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.SelectWordLeft(false)" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.DeleteSelection()" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("DeleteWordLeft", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Delete deletes the next character" & @CRLF & _ " func (v *View) Delete(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("Delete", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.DeleteSelection()" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " } else {" & @CRLF & _ " loc := v.Cursor.Loc" & @CRLF & _ " if loc.LessThan(v.Buf.End()) {" & @CRLF & _ " v.Buf.Remove(loc, loc.Move(1, v.Buf))" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Delete", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // IndentSelection indents the current selection" & @CRLF & _ " func (v *View) IndentSelection(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("IndentSelection", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " start := v.Cursor.CurSelection[0]" & @CRLF & _ " end := v.Cursor.CurSelection[1]" & @CRLF & _ " if end.Y < start.Y {" & @CRLF & _ " start, end = end, start" & @CRLF & _ " v.Cursor.SetSelectionStart(start)" & @CRLF & _ " v.Cursor.SetSelectionEnd(end)" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " startY := start.Y" & @CRLF & _ " endY := end.Move(-1, v.Buf).Y" & @CRLF & _ " endX := end.Move(-1, v.Buf).X" & @CRLF & _ " tabsize := len(v.Buf.IndentString())" & @CRLF & _ " for y := startY; y <= endY; y++ {" & @CRLF & _ " v.Buf.Insert(Loc{0, y}, v.Buf.IndentString())" & @CRLF & _ " if y == startY && start.X > 0 {" & @CRLF & _ " v.Cursor.SetSelectionStart(start.Move(tabsize, v.Buf))" & @CRLF & _ " }" & @CRLF & _ " if y == endY {" & @CRLF & _ " v.Cursor.SetSelectionEnd(Loc{endX + tabsize + 1, endY})" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.Relocate()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("IndentSelection", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // OutdentLine moves the current line back one indentation" & @CRLF & _ " func (v *View) OutdentLine(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("OutdentLine", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " for x := 0; x < len(v.Buf.IndentString()); x++ {" & @CRLF & _ " if len(GetLeadingWhitespace(v.Buf.Line(v.Cursor.Y))) == 0 {" & @CRLF & _ " break" & @CRLF & _ " }" & @CRLF & _ " v.Buf.Remove(Loc{0, v.Cursor.Y}, Loc{1, v.Cursor.Y})" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.Relocate()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("OutdentLine", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // OutdentSelection takes the current selection and moves it back one indent level" & @CRLF & _ " func (v *View) OutdentSelection(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("OutdentSelection", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " start := v.Cursor.CurSelection[0]" & @CRLF & _ " end := v.Cursor.CurSelection[1]" & @CRLF & _ " if end.Y < start.Y {" & @CRLF & _ " start, end = end, start" & @CRLF & _ " v.Cursor.SetSelectionStart(start)" & @CRLF & _ " v.Cursor.SetSelectionEnd(end)" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " startY := start.Y" & @CRLF & _ " endY := end.Move(-1, v.Buf).Y" & @CRLF & _ " for y := startY; y <= endY; y++ {" & @CRLF & _ " for x := 0; x < len(v.Buf.IndentString()); x++ {" & @CRLF & _ " if len(GetLeadingWhitespace(v.Buf.Line(y))) == 0 {" & @CRLF & _ " break" & @CRLF & _ " }" & @CRLF & _ " v.Buf.Remove(Loc{0, y}, Loc{1, y})" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.Relocate()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("OutdentSelection", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // InsertTab inserts a tab or spaces" & @CRLF & _ " func (v *View) InsertTab(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("InsertTab", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " tabBytes := len(v.Buf.IndentString())" & @CRLF & _ " bytesUntilIndent := tabBytes - (v.Cursor.GetVisualX() % tabBytes)" & @CRLF & _ " v.Buf.Insert(v.Cursor.Loc, v.Buf.IndentString()[:bytesUntilIndent])" & @CRLF & _ " // for i := 0; i < bytesUntilIndent; i++ {" & @CRLF & _ " // v.Cursor.Right()" & @CRLF & _ " // }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("InsertTab", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SaveAll saves all open buffers" & @CRLF & _ " func (v *View) SaveAll(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("SaveAll", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " for _, t := range tabs {" & @CRLF & _ " for _, v := range t.Views {" & @CRLF & _ " v.Save(false)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SaveAll", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Save the buffer to disk" & @CRLF & _ " func (v *View) Save(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("Save", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Type.Scratch == true {" & @CRLF & _ " // We can't save any view type with scratch set. eg help and log text" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ " // If this is an empty buffer, ask for a filename" & @CRLF & _ " if v.Buf.Path == "" {" & @CRLF & _ " v.SaveAs(false)" & @CRLF & _ " } else {" & @CRLF & _ " v.saveToFile(v.Buf.Path)" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Save", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // This function saves the buffer to `filename` and changes the buffer's path and name" & @CRLF & _ " // to `filename` if the save is successful" & @CRLF & _ " func (v *View) saveToFile(filename string) {" & @CRLF & _ " err := v.Buf.SaveAs(filename)" & @CRLF & _ " if err != nil {" & @CRLF & _ " if strings.HasSuffix(err.Error(), "permission denied") {" & @CRLF & _ " choice, _ := messenger.YesNoPrompt("Permission denied. Do you want to save this file using sudo? (y,n)")" & @CRLF & _ " if choice {" & @CRLF & _ " err = v.Buf.SaveAsWithSudo(filename)" & @CRLF & _ " if err != nil {" & @CRLF & _ " messenger.Error(err.Error())" & @CRLF & _ " } else {" & @CRLF & _ " v.Buf.Path = filename" & @CRLF & _ " v.Buf.name = filename" & @CRLF & _ " messenger.Message("Saved " + filename)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " messenger.Reset()" & @CRLF & _ " messenger.Clear()" & @CRLF & _ " } else {" & @CRLF & _ " messenger.Error(err.Error())" & @CRLF & _ " }" & @CRLF & _ " } else {" & @CRLF & _ " v.Buf.Path = filename" & @CRLF & _ " v.Buf.name = filename" & @CRLF & _ " messenger.Message("Saved " + filename)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SaveAs saves the buffer to disk with the given name" & @CRLF & _ " func (v *View) SaveAs(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("SaveAs", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " filename, canceled := messenger.Prompt("Filename: ", "", "Save", NoCompletion)" & @CRLF & _ " if !canceled {" & @CRLF & _ " // the filename might or might not be quoted, so unquote first then join the strings." & @CRLF & _ " args, err := shellwords.Split(filename)" & @CRLF & _ " filename = strings.Join(args, " ")" & @CRLF & _ " if err != nil {" & @CRLF & _ " messenger.Error("Error parsing arguments: ", err)" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ " v.saveToFile(filename)" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " PostActionCall("SaveAs", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Find opens a prompt and searches forward for the input" & @CRLF & _ " func (v *View) Find(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("Find", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " searchStr := """ & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " searchStart = v.Cursor.CurSelection[1]" & @CRLF & _ " searchStart = v.Cursor.CurSelection[1]" & @CRLF & _ " searchStr = v.Cursor.GetSelection()" & @CRLF & _ " } else {" & @CRLF & _ " searchStart = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " BeginSearch(searchStr)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Find", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // FindNext searches forwards for the last used search term" & @CRLF & _ " func (v *View) FindNext(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("FindNext", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " searchStart = v.Cursor.CurSelection[1]" & @CRLF & _ " // lastSearch = v.Cursor.GetSelection()" & @CRLF & _ " } else {" & @CRLF & _ " searchStart = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " if lastSearch == "" {" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " messenger.Message("Finding: " + lastSearch)" & @CRLF & _ " Search(lastSearch, v, true)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("FindNext", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // FindPrevious searches backwards for the last used search term" & @CRLF & _ " func (v *View) FindPrevious(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("FindPrevious", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " searchStart = v.Cursor.CurSelection[0]" & @CRLF & _ " } else {" & @CRLF & _ " searchStart = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " messenger.Message("Finding: " + lastSearch)" & @CRLF & _ " Search(lastSearch, v, false)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("FindPrevious", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Undo undoes the last action" & @CRLF & _ " func (v *View) Undo(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("Undo", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Buf.curCursor == 0 {" & @CRLF & _ " v.Buf.clearCursors()" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Buf.Undo()" & @CRLF & _ " messenger.Message("Undid action")" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Undo", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Redo redoes the last action" & @CRLF & _ " func (v *View) Redo(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("Redo", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Buf.curCursor == 0 {" & @CRLF & _ " v.Buf.clearCursors()" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Buf.Redo()" & @CRLF & _ " messenger.Message("Redid action")" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Redo", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Copy the selection to the system clipboard" & @CRLF & _ " func (v *View) Copy(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("Copy", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.CopySelection("clipboard")" & @CRLF & _ " v.freshClip = true" & @CRLF & _ " messenger.Message("Copied selection")" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Copy", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // CutLine cuts the current line to the clipboard" & @CRLF & _ " func (v *View) CutLine(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("CutLine", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Cursor.SelectLine()" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ " if v.freshClip == true {" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " if clip, err := clipboard.ReadAll("clipboard"); err != nil {" & @CRLF & _ " messenger.Error(err)" & @CRLF & _ " } else {" & @CRLF & _ " clipboard.WriteAll(clip+v.Cursor.GetSelection(), "clipboard")" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " } else if time.Since(v.lastCutTime)/time.Second > 10*time.Second || v.freshClip == false {" & @CRLF & _ " v.Copy(true)" & @CRLF & _ " }" & @CRLF & _ " v.freshClip = true" & @CRLF & _ " v.lastCutTime = time.Now()" & @CRLF & _ " v.Cursor.DeleteSelection()" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " messenger.Message("Cut line")" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("CutLine", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Cut the selection to the system clipboard" & @CRLF & _ " func (v *View) Cut(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("Cut", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.CopySelection("clipboard")" & @CRLF & _ " v.Cursor.DeleteSelection()" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " v.freshClip = true" & @CRLF & _ " messenger.Message("Cut selection")" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Cut", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " } else {" & @CRLF & _ " return v.CutLine(usePlugin)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // DuplicateLine duplicates the current line or selection" & @CRLF & _ " func (v *View) DuplicateLine(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("DuplicateLine", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Buf.Insert(v.Cursor.CurSelection[1], v.Cursor.GetSelection())" & @CRLF & _ " } else {" & @CRLF & _ " v.Cursor.End()" & @CRLF & _ " v.Buf.Insert(v.Cursor.Loc, "\n"+v.Buf.Line(v.Cursor.Y))" & @CRLF & _ " // v.Cursor.Right()" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " messenger.Message("Duplicated line")" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("DuplicateLine", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // DeleteLine deletes the current line" & @CRLF & _ " func (v *View) DeleteLine(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("DeleteLine", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Cursor.SelectLine()" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.DeleteSelection()" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " messenger.Message("Deleted line")" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("DeleteLine", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // MoveLinesUp moves up the current line or selected lines if any" & @CRLF & _ " func (v *View) MoveLinesUp(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("MoveLinesUp", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " if v.Cursor.CurSelection[0].Y == 0 {" & @CRLF & _ " messenger.Message("Can not move further up")" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " start := v.Cursor.CurSelection[0].Y" & @CRLF & _ " end := v.Cursor.CurSelection[1].Y" & @CRLF & _ " if start > end {" & @CRLF & _ " end, start = start, end" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Buf.MoveLinesUp(" & @CRLF & _ " start," & @CRLF & _ " end," & @CRLF & _ " )" & @CRLF & _ " v.Cursor.CurSelection[1].Y -= 1" & @CRLF & _ " messenger.Message("Moved up selected line(s)")" & @CRLF & _ " } else {" & @CRLF & _ " if v.Cursor.Loc.Y == 0 {" & @CRLF & _ " messenger.Message("Can not move further up")" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " v.Buf.MoveLinesUp(" & @CRLF & _ " v.Cursor.Loc.Y," & @CRLF & _ " v.Cursor.Loc.Y+1," & @CRLF & _ " )" & @CRLF & _ " messenger.Message("Moved up current line")" & @CRLF & _ " }" & @CRLF & _ " v.Buf.IsModified = true" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("MoveLinesUp", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // MoveLinesDown moves down the current line or selected lines if any" & @CRLF & _ " func (v *View) MoveLinesDown(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("MoveLinesDown", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " if v.Cursor.CurSelection[1].Y >= len(v.Buf.lines) {" & @CRLF & _ " messenger.Message("Can not move further down")" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " start := v.Cursor.CurSelection[0].Y" & @CRLF & _ " end := v.Cursor.CurSelection[1].Y" & @CRLF & _ " if start > end {" & @CRLF & _ " end, start = start, end" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Buf.MoveLinesDown(" & @CRLF & _ " start," & @CRLF & _ " end," & @CRLF & _ " )" & @CRLF & _ " messenger.Message("Moved down selected line(s)")" & @CRLF & _ " } else {" & @CRLF & _ " if v.Cursor.Loc.Y >= len(v.Buf.lines)-1 {" & @CRLF & _ " messenger.Message("Can not move further down")" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " v.Buf.MoveLinesDown(" & @CRLF & _ " v.Cursor.Loc.Y," & @CRLF & _ " v.Cursor.Loc.Y+1," & @CRLF & _ " )" & @CRLF & _ " messenger.Message("Moved down current line")" & @CRLF & _ " }" & @CRLF & _ " v.Buf.IsModified = true" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("MoveLinesDown", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Paste whatever is in the system clipboard into the buffer" & @CRLF & _ " // Delete and paste if the user has a selection" & @CRLF & _ " func (v *View) Paste(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("Paste", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " clip, _ := clipboard.ReadAll("clipboard")" & @CRLF & _ " v.paste(clip)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Paste", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // PastePrimary pastes from the primary clipboard (only use on linux)" & @CRLF & _ " func (v *View) PastePrimary(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("Paste", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " clip, _ := clipboard.ReadAll("primary")" & @CRLF & _ " v.paste(clip)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Paste", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // JumpToMatchingBrace moves the cursor to the matching brace if it is" & @CRLF & _ " // currently on a brace" & @CRLF & _ " func (v *View) JumpToMatchingBrace(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("JumpToMatchingBrace", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " for _, bp := range bracePairs {" & @CRLF & _ " r := v.Cursor.RuneUnder(v.Cursor.X)" & @CRLF & _ " if r == bp[0] || r == bp[1] {" & @CRLF & _ " matchingBrace := v.Buf.FindMatchingBrace(bp, v.Cursor.Loc)" & @CRLF & _ " v.Cursor.GotoLoc(matchingBrace)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("JumpToMatchingBrace", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectAll selects the entire buffer" & @CRLF & _ " func (v *View) SelectAll(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectAll", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Cursor.SetSelectionStart(v.Buf.Start())" & @CRLF & _ " v.Cursor.SetSelectionEnd(v.Buf.End())" & @CRLF & _ " // Put the cursor at the beginning" & @CRLF & _ " v.Cursor.X = 0" & @CRLF & _ " v.Cursor.Y = 0" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectAll", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // OpenFile opens a new file in the buffer" & @CRLF & _ " func (v *View) OpenFile(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("OpenFile", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.CanClose() {" & @CRLF & _ " input, canceled := messenger.Prompt("> ", "open ", "Open", CommandCompletion)" & @CRLF & _ " if !canceled {" & @CRLF & _ " HandleCommand(input)" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("OpenFile", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Start moves the viewport to the start of the buffer" & @CRLF & _ " func (v *View) Start(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("Start", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Topline = 0" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Start", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // End moves the viewport to the end of the buffer" & @CRLF & _ " func (v *View) End(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("End", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Height > v.Buf.NumLines {" & @CRLF & _ " v.Topline = 0" & @CRLF & _ " } else {" & @CRLF & _ " v.Topline = v.Buf.NumLines - v.Height" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("End", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // PageUp scrolls the view up a page" & @CRLF & _ " func (v *View) PageUp(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("PageUp", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Topline > v.Height {" & @CRLF & _ " v.ScrollUp(v.Height)" & @CRLF & _ " } else {" & @CRLF & _ " v.Topline = 0" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("PageUp", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // PageDown scrolls the view down a page" & @CRLF & _ " func (v *View) PageDown(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("PageDown", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Buf.NumLines-(v.Topline+v.Height) > v.Height {" & @CRLF & _ " v.ScrollDown(v.Height)" & @CRLF & _ " } else if v.Buf.NumLines >= v.Height {" & @CRLF & _ " v.Topline = v.Buf.NumLines - v.Height" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("PageDown", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectPageUp selects up one page" & @CRLF & _ " func (v *View) SelectPageUp(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectPageUp", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.OrigSelection[0] = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.UpN(v.Height)" & @CRLF & _ " v.Cursor.SelectTo(v.Cursor.Loc)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectPageUp", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SelectPageDown selects down one page" & @CRLF & _ " func (v *View) SelectPageDown(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("SelectPageDown", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if !v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.OrigSelection[0] = v.Cursor.Loc" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.DownN(v.Height)" & @CRLF & _ " v.Cursor.SelectTo(v.Cursor.Loc)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("SelectPageDown", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // CursorPageUp places the cursor a page up" & @CRLF & _ " func (v *View) CursorPageUp(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("CursorPageUp", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.deselect(0)" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.Loc = v.Cursor.CurSelection[0]" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " v.Cursor.StoreVisualX()" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.UpN(v.Height)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("CursorPageUp", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // CursorPageDown places the cursor a page up" & @CRLF & _ " func (v *View) CursorPageDown(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("CursorPageDown", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.deselect(0)" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.Loc = v.Cursor.CurSelection[1]" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " v.Cursor.StoreVisualX()" & @CRLF & _ " }" & @CRLF & _ " v.Cursor.DownN(v.Height)" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("CursorPageDown", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // HalfPageUp scrolls the view up half a page" & @CRLF & _ " func (v *View) HalfPageUp(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("HalfPageUp", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Topline > v.Height/2 {" & @CRLF & _ " v.ScrollUp(v.Height / 2)" & @CRLF & _ " } else {" & @CRLF & _ " v.Topline = 0" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("HalfPageUp", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // HalfPageDown scrolls the view down half a page" & @CRLF & _ " func (v *View) HalfPageDown(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("HalfPageDown", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Buf.NumLines-(v.Topline+v.Height) > v.Height/2 {" & @CRLF & _ " v.ScrollDown(v.Height / 2)" & @CRLF & _ " } else {" & @CRLF & _ " if v.Buf.NumLines >= v.Height {" & @CRLF & _ " v.Topline = v.Buf.NumLines - v.Height" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("HalfPageDown", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // ToggleRuler turns line numbers off and on" & @CRLF & _ " func (v *View) ToggleRuler(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("ToggleRuler", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Buf.Settings["ruler"] == false {" & @CRLF & _ " v.Buf.Settings["ruler"] = true" & @CRLF & _ " messenger.Message("Enabled ruler")" & @CRLF & _ " } else {" & @CRLF & _ " v.Buf.Settings["ruler"] = false" & @CRLF & _ " messenger.Message("Disabled ruler")" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("ToggleRuler", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // JumpLine jumps to a line and moves the view accordingly." & @CRLF & _ " func (v *View) JumpLine(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("JumpLine", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Prompt for line number" & @CRLF & _ " message := fmt.Sprintf("Jump to line:col (1 - %v) # ", v.Buf.NumLines)" & @CRLF & _ " input, canceled := messenger.Prompt(message, "", "LineNumber", NoCompletion)" & @CRLF & _ " if canceled {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ " var lineInt int" & @CRLF & _ " var colInt int" & @CRLF & _ " var err error" & @CRLF & _ " if strings.Contains(input, ":") {" & @CRLF & _ " split := strings.Split(input, ":")" & @CRLF & _ " lineInt, err = strconv.Atoi(split[0])" & @CRLF & _ " if err != nil {" & @CRLF & _ " messenger.Message("Invalid line number")" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ " colInt, err = strconv.Atoi(split[1])" & @CRLF & _ " if err != nil {" & @CRLF & _ " messenger.Message("Invalid column number")" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ " } else {" & @CRLF & _ " lineInt, err = strconv.Atoi(input)" & @CRLF & _ " if err != nil {" & @CRLF & _ " messenger.Message("Invalid line number")" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " lineInt--" & @CRLF & _ " // Move cursor and view if possible." & @CRLF & _ " if lineInt < v.Buf.NumLines && lineInt >= 0 {" & @CRLF & _ " v.Cursor.X = colInt" & @CRLF & _ " v.Cursor.Y = lineInt" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("JumpLine", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " messenger.Error("Only ", v.Buf.NumLines, " lines to jump")" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // ClearStatus clears the messenger bar" & @CRLF & _ " func (v *View) ClearStatus(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("ClearStatus", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " messenger.Message("")" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("ClearStatus", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // ToggleHelp toggles the help screen" & @CRLF & _ " func (v *View) ToggleHelp(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("ToggleHelp", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Type != vtHelp {" & @CRLF & _ " // Open the default help" & @CRLF & _ " v.openHelp("help")" & @CRLF & _ " } else {" & @CRLF & _ " v.Quit(true)" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("ToggleHelp", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // ToggleKeyMenu toggles the keymenu option and resizes all tabs" & @CRLF & _ " func (v *View) ToggleKeyMenu(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("ToggleBindings", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " globalSettings["keymenu"] = !globalSettings["keymenu"].(bool)" & @CRLF & _ " for _, tab := range tabs {" & @CRLF & _ " tab.Resize()" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("ToggleBindings", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // ShellMode opens a terminal to run a shell command" & @CRLF & _ " func (v *View) ShellMode(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("ShellMode", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " input, canceled := messenger.Prompt("$ ", "", "Shell", NoCompletion)" & @CRLF & _ " if !canceled {" & @CRLF & _ " // The true here is for openTerm to make the command interactive" & @CRLF & _ " HandleShellCommand(input, true, true)" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("ShellMode", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // CommandMode lets the user enter a command" & @CRLF & _ " func (v *View) CommandMode(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("CommandMode", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " input, canceled := messenger.Prompt("> ", "", "Command", CommandCompletion)" & @CRLF & _ " if !canceled {" & @CRLF & _ " HandleCommand(input)" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("CommandMode", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // ToggleOverwriteMode lets the user toggle the text overwrite mode" & @CRLF & _ " func (v *View) ToggleOverwriteMode(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("ToggleOverwriteMode", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.isOverwriteMode = !v.isOverwriteMode" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("ToggleOverwriteMode", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Escape leaves current mode" & @CRLF & _ " func (v *View) Escape(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " // check if user is searching, or the last search is still active" & @CRLF & _ " if searching || lastSearch != "" {" & @CRLF & _ " ExitSearch(v)" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " // check if a prompt is shown, hide it and don't quit" & @CRLF & _ " if messenger.hasPrompt {" & @CRLF & _ " messenger.Reset() // FIXME" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Quit this will close the current tab or view that is open" & @CRLF & _ " func (v *View) Quit(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("Quit", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Make sure not to quit if there are unsaved changes" & @CRLF & _ " if v.CanClose() {" & @CRLF & _ " v.CloseBuffer()" & @CRLF & _ " if len(tabs[curTab].Views) > 1 {" & @CRLF & _ " v.splitNode.Delete()" & @CRLF & _ " tabs[v.TabNum].Cleanup()" & @CRLF & _ " tabs[v.TabNum].Resize()" & @CRLF & _ " } else if len(tabs) > 1 {" & @CRLF & _ " if len(tabs[v.TabNum].Views) == 1 {" & @CRLF & _ " tabs = tabs[:v.TabNum+copy(tabs[v.TabNum:], tabs[v.TabNum+1:])]" & @CRLF & _ " for i, t := range tabs {" & @CRLF & _ " t.SetNum(i)" & @CRLF & _ " }" & @CRLF & _ " if curTab >= len(tabs) {" & @CRLF & _ " curTab--" & @CRLF & _ " }" & @CRLF & _ " if curTab == 0 {" & @CRLF & _ " CurView().ToggleTabbar()" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " } else {" & @CRLF & _ " if usePlugin {" & @CRLF & _ " PostActionCall("Quit", v)" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " screen.Fini()" & @CRLF & _ " messenger.SaveHistory()" & @CRLF & _ " os.Exit(0)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Quit", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // QuitAll quits the whole editor; all splits and tabs" & @CRLF & _ " func (v *View) QuitAll(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("QuitAll", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " closeAll := true" & @CRLF & _ " for _, tab := range tabs {" & @CRLF & _ " for _, v := range tab.Views {" & @CRLF & _ " if !v.CanClose() {" & @CRLF & _ " closeAll = false" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if closeAll {" & @CRLF & _ " // only quit if all of the buffers can be closed and the user confirms that they actually want to quit everything" & @CRLF & _ " shouldQuit, _ := messenger.YesNoPrompt("Do you want to quit micro (all open files will be closed)?")" & @CRLF & _ "" & @CRLF & _ " if shouldQuit {" & @CRLF & _ " for _, tab := range tabs {" & @CRLF & _ " for _, v := range tab.Views {" & @CRLF & _ " v.CloseBuffer()" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " PostActionCall("QuitAll", v)" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " screen.Fini()" & @CRLF & _ " messenger.SaveHistory()" & @CRLF & _ " os.Exit(0)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // AddTab adds a new tab with an empty buffer" & @CRLF & _ " func (v *View) AddTab(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("AddTab", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " tab := NewTabFromView(NewView(NewBufferFromString("", "")))" & @CRLF & _ " tab.SetNum(len(tabs))" & @CRLF & _ " tabs = append(tabs, tab)" & @CRLF & _ " curTab = len(tabs) - 1" & @CRLF & _ " if len(tabs) == 2 {" & @CRLF & _ " for _, t := range tabs {" & @CRLF & _ " for _, v := range t.Views {" & @CRLF & _ " v.ToggleTabbar()" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("AddTab", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // PreviousTab switches to the previous tab in the tab list" & @CRLF & _ " func (v *View) PreviousTab(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("PreviousTab", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if curTab > 0 {" & @CRLF & _ " curTab--" & @CRLF & _ " } else if curTab == 0 {" & @CRLF & _ " curTab = len(tabs) - 1" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("PreviousTab", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // NextTab switches to the next tab in the tab list" & @CRLF & _ " func (v *View) NextTab(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("NextTab", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if curTab < len(tabs)-1 {" & @CRLF & _ " curTab++" & @CRLF & _ " } else if curTab == len(tabs)-1 {" & @CRLF & _ " curTab = 0" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("NextTab", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // VSplitBinding opens an empty vertical split" & @CRLF & _ " func (v *View) VSplitBinding(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("VSplit", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.VSplit(NewBufferFromString("", ""))" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("VSplit", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // HSplitBinding opens an empty horizontal split" & @CRLF & _ " func (v *View) HSplitBinding(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("HSplit", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.HSplit(NewBufferFromString("", ""))" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("HSplit", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Unsplit closes all splits in the current tab except the active one" & @CRLF & _ " func (v *View) Unsplit(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("Unsplit", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " curView := tabs[curTab].CurView" & @CRLF & _ " for i := len(tabs[curTab].Views) - 1; i >= 0; i-- {" & @CRLF & _ " view := tabs[curTab].Views[i]" & @CRLF & _ " if view != nil && view.Num != curView {" & @CRLF & _ " view.Quit(true)" & @CRLF & _ " // messenger.Message("Quit ", view.Buf.Path)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("Unsplit", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // NextSplit changes the view to the next split" & @CRLF & _ " func (v *View) NextSplit(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("NextSplit", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " tab := tabs[curTab]" & @CRLF & _ " if tab.CurView < len(tab.Views)-1 {" & @CRLF & _ " tab.CurView++" & @CRLF & _ " } else {" & @CRLF & _ " tab.CurView = 0" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("NextSplit", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // PreviousSplit changes the view to the previous split" & @CRLF & _ " func (v *View) PreviousSplit(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("PreviousSplit", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " tab := tabs[curTab]" & @CRLF & _ " if tab.CurView > 0 {" & @CRLF & _ " tab.CurView--" & @CRLF & _ " } else {" & @CRLF & _ " tab.CurView = len(tab.Views) - 1" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("PreviousSplit", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " var curMacro []interface{}" & @CRLF & _ " var recordingMacro bool" & @CRLF & _ "" & @CRLF & _ " // ToggleMacro toggles recording of a macro" & @CRLF & _ " func (v *View) ToggleMacro(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("ToggleMacro", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " recordingMacro = !recordingMacro" & @CRLF & _ "" & @CRLF & _ " if recordingMacro {" & @CRLF & _ " curMacro = []interface{}{}" & @CRLF & _ " messenger.Message("Recording")" & @CRLF & _ " } else {" & @CRLF & _ " messenger.Message("Stopped recording")" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("ToggleMacro", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // PlayMacro plays back the most recently recorded macro" & @CRLF & _ " func (v *View) PlayMacro(usePlugin bool) bool {" & @CRLF & _ " if usePlugin && !PreActionCall("PlayMacro", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " for _, action := range curMacro {" & @CRLF & _ " switch t := action.(type) {" & @CRLF & _ " case rune:" & @CRLF & _ " // Insert a character" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.DeleteSelection()" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " }" & @CRLF & _ " v.Buf.Insert(v.Cursor.Loc, string(t))" & @CRLF & _ " // v.Cursor.Right()" & @CRLF & _ "" & @CRLF & _ " for pl := range loadedPlugins {" & @CRLF & _ " _, err := Call(pl+".onRune", string(t), v)" & @CRLF & _ " if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {" & @CRLF & _ " TermMessage(err)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " case func(*View, bool) bool:" & @CRLF & _ " t(v, true)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("PlayMacro", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SpawnMultiCursor creates a new multiple cursor at the next occurrence of the current selection or current word" & @CRLF & _ " func (v *View) SpawnMultiCursor(usePlugin bool) bool {" & @CRLF & _ " spawner := v.Buf.cursors[len(v.Buf.cursors)-1]" & @CRLF & _ " // You can only spawn a cursor from the main cursor" & @CRLF & _ " if v.Cursor == spawner {" & @CRLF & _ " if usePlugin && !PreActionCall("SpawnMultiCursor", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if !spawner.HasSelection() {" & @CRLF & _ " spawner.SelectWord()" & @CRLF & _ " } else {" & @CRLF & _ " c := &Cursor{" & @CRLF & _ " buf: v.Buf," & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " sel := spawner.GetSelection()" & @CRLF & _ "" & @CRLF & _ " searchStart = spawner.CurSelection[1]" & @CRLF & _ " v.Cursor = c" & @CRLF & _ " Search(regexp.QuoteMeta(sel), v, true)" & @CRLF & _ "" & @CRLF & _ " for _, cur := range v.Buf.cursors {" & @CRLF & _ " if c.Loc == cur.Loc {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " v.Buf.cursors = append(v.Buf.cursors, c)" & @CRLF & _ " v.Buf.UpdateCursors()" & @CRLF & _ " v.Relocate()" & @CRLF & _ " v.Cursor = spawner" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " PostActionCall("SpawnMultiCursor", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SpawnMultiCursorSelect adds a cursor at the beginning of each line of a selection" & @CRLF & _ " func (v *View) SpawnMultiCursorSelect(usePlugin bool) bool {" & @CRLF & _ " if v.Cursor == &v.Buf.Cursor {" & @CRLF & _ " if usePlugin && !PreActionCall("SpawnMultiCursorSelect", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // Avoid cases where multiple cursors already exist, that would create problems" & @CRLF & _ " if len(v.Buf.cursors) > 1 {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " var startLine int" & @CRLF & _ " var endLine int" & @CRLF & _ "" & @CRLF & _ " a, b := v.Cursor.CurSelection[0].Y, v.Cursor.CurSelection[1].Y" & @CRLF & _ " if a > b {" & @CRLF & _ " startLine, endLine = b, a" & @CRLF & _ " } else {" & @CRLF & _ " startLine, endLine = a, b" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if v.Cursor.HasSelection() {" & @CRLF & _ " v.Cursor.ResetSelection()" & @CRLF & _ " v.Cursor.GotoLoc(Loc{0, startLine})" & @CRLF & _ "" & @CRLF & _ " for i := startLine; i <= endLine; i++ {" & @CRLF & _ " c := &Cursor{" & @CRLF & _ " buf: v.Buf," & @CRLF & _ " }" & @CRLF & _ " c.GotoLoc(Loc{0, i})" & @CRLF & _ " v.Buf.cursors = append(v.Buf.cursors, c)" & @CRLF & _ " }" & @CRLF & _ " v.Buf.MergeCursors()" & @CRLF & _ " v.Buf.UpdateCursors()" & @CRLF & _ " } else {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " PostActionCall("SpawnMultiCursorSelect", v)" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " messenger.Message("Added cursors from selection")" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // MouseMultiCursor is a mouse action which puts a new cursor at the mouse position" & @CRLF & _ " func (v *View) MouseMultiCursor(usePlugin bool, e *tcell.EventMouse) bool {" & @CRLF & _ " if v.Cursor == &v.Buf.Cursor {" & @CRLF & _ " if usePlugin && !PreActionCall("SpawnMultiCursorAtMouse", v, e) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ " x, y := e.Position()" & @CRLF & _ " x -= v.lineNumOffset - v.leftCol + v.x" & @CRLF & _ " y += v.Topline - v.y" & @CRLF & _ "" & @CRLF & _ " c := &Cursor{" & @CRLF & _ " buf: v.Buf," & @CRLF & _ " }" & @CRLF & _ " v.Cursor = c" & @CRLF & _ " v.MoveToMouseClick(x, y)" & @CRLF & _ " v.Relocate()" & @CRLF & _ " v.Cursor = &v.Buf.Cursor" & @CRLF & _ "" & @CRLF & _ " v.Buf.cursors = append(v.Buf.cursors, c)" & @CRLF & _ " v.Buf.MergeCursors()" & @CRLF & _ " v.Buf.UpdateCursors()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " PostActionCall("SpawnMultiCursorAtMouse", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // SkipMultiCursor moves the current multiple cursor to the next available position" & @CRLF & _ " func (v *View) SkipMultiCursor(usePlugin bool) bool {" & @CRLF & _ " cursor := v.Buf.cursors[len(v.Buf.cursors)-1]" & @CRLF & _ "" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("SkipMultiCursor", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ " sel := cursor.GetSelection()" & @CRLF & _ "" & @CRLF & _ " searchStart = cursor.CurSelection[1]" & @CRLF & _ " v.Cursor = cursor" & @CRLF & _ " Search(regexp.QuoteMeta(sel), v, true)" & @CRLF & _ " v.Relocate()" & @CRLF & _ " v.Cursor = cursor" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " PostActionCall("SkipMultiCursor", v)" & @CRLF & _ " }" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // RemoveMultiCursor removes the latest multiple cursor" & @CRLF & _ " func (v *View) RemoveMultiCursor(usePlugin bool) bool {" & @CRLF & _ " end := len(v.Buf.cursors)" & @CRLF & _ " if end > 1 {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("RemoveMultiCursor", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Buf.cursors[end-1] = nil" & @CRLF & _ " v.Buf.cursors = v.Buf.cursors[:end-1]" & @CRLF & _ " v.Buf.UpdateCursors()" & @CRLF & _ " v.Relocate()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("RemoveMultiCursor", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " } else {" & @CRLF & _ " v.RemoveAllMultiCursors(usePlugin)" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " // RemoveAllMultiCursors removes all cursors except the base cursor" & @CRLF & _ " func (v *View) RemoveAllMultiCursors(usePlugin bool) bool {" & @CRLF & _ " if v.mainCursor() {" & @CRLF & _ " if usePlugin && !PreActionCall("RemoveAllMultiCursors", v) {" & @CRLF & _ " return false" & @CRLF & _ " }" & @CRLF & _ "" & @CRLF & _ " v.Buf.clearCursors()" & @CRLF & _ " v.Relocate()" & @CRLF & _ "" & @CRLF & _ " if usePlugin {" & @CRLF & _ " return PostActionCall("RemoveAllMultiCursors", v)" & @CRLF & _ " }" & @CRLF & _ " return true" & @CRLF & _ " }" & @CRLF & _ " return false" & @CRLF & _ " }" Local $sSubst = "--[[\n${statementDescComment}${statement}\n]]--" Local $sResult = StringRegExpReplace($sString, $sRegex, $sSubst) MsgBox($MB_SYSTEMMODAL, "Result", $sResult)

Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for AutoIt, please visit: https://www.autoitscript.com/autoit3/docs/functions/StringRegExp.htm