Compare commits

..

17 Commits

Author SHA1 Message Date
Zachary Yedidia
a02ae3ceed Replace home directory before performing SaveAs
Fixes #820
2017-09-26 22:55:06 -04:00
MrSndmn
54c02f4781 Perl syntax highlighting fix (#818)
* Perl syntax highlighting fix

* Useless escapes removed
2017-09-24 11:59:57 -04:00
Zachary Yedidia
a5e721b107 Set fastdirty on for files larger than 50kb 2017-09-23 21:18:37 -04:00
Zachary Yedidia
12a4dd58f3 Only replace '~' with home if at start of path
Ref #757
2017-09-23 20:56:08 -04:00
Zachary Yedidia
5a7ddb8330 Add autocompletion for option values
Closes #555
2017-09-23 20:47:19 -04:00
Zachary Yedidia
cb75531818 Make mouse option global option
Fixes #816
2017-09-21 17:10:53 -04:00
Zachary Yedidia
6229a0579f Update tcell
The latest commit to tcell should fix behavior for large pastes.

Fixes #815
2017-09-19 13:21:09 -04:00
Zachary Yedidia
fb980bb695 Add option for very accurate dirty flag
Set the `fastdirty` option flag to off if you really want accurate
reporting on whether the buffer is modified. This is more resource
intensive but it can be useful for people who don't mind.

Closes #787
Closes #467
2017-09-17 23:33:18 -04:00
Zachary Yedidia
19dc9d7bbc Fix options and make usage text much more readable
Now micro -h will just show you the important information and if you
want to see each individual option's help text use micro -options.
2017-09-17 22:11:26 -04:00
Zachary Yedidia
1e55b6f6b3 Only register double click on equal mouse location 2017-09-17 18:31:32 -04:00
Zachary Yedidia
0a35bfe2f5 Update readme 2017-09-15 16:25:01 -04:00
Zachary Yedidia
2f587c6d48 Fix moving to end of line on cursor down 2017-09-15 16:09:33 -04:00
Zachary Yedidia
5b426aee86 Update tcell 2017-09-15 14:15:21 -04:00
Zachary Yedidia
f700769b27 Update tcell 2017-09-15 13:33:06 -04:00
Zachary Yedidia
04b672eebe Update tcell 2017-09-15 10:50:56 -04:00
Zachary Yedidia
f7238e8e53 Update tcell 2017-09-14 17:29:25 -04:00
Zachary Yedidia
33cb39d318 Use type.keyword instead of keyword
Some syntax files used keyword from an old version when they should have
been using type.keyword.

Fixes #811
2017-09-13 18:00:47 -04:00
22 changed files with 226 additions and 155 deletions

View File

@@ -50,7 +50,7 @@ You can also check out the website for Micro at https://micro-editor.github.io.
* Macros
* Common editor things such as undo/redo, line numbers, Unicode support, softwrap...
Although not yet implemented, I hope to add more features such as autocompletion ([#174](https://github.com/zyedidia/micro/issues/174)), and multiple cursors ([#5](https://github.com/zyedidia/micro/issues/5)) in the future.
Although not yet implemented, I hope to add more features such as autocompletion ([#174](https://github.com/zyedidia/micro/issues/174)) or a tree view ([#249](https://github.com/zyedidia/micro/issues/249)) in the future.
# Installation

View File

@@ -78,7 +78,7 @@ func (v *View) MousePress(usePlugin bool, e *tcell.EventMouse) bool {
v.Cursor.ResetSelection()
v.Relocate()
}
if time.Since(v.lastClickTime)/time.Millisecond < doubleClickThreshold {
if time.Since(v.lastClickTime)/time.Millisecond < doubleClickThreshold && (x == v.lastLoc.X && y == v.lastLoc.Y) {
if v.doubleClick {
// Triple click
v.lastClickTime = time.Now()
@@ -119,6 +119,8 @@ func (v *View) MousePress(usePlugin bool, e *tcell.EventMouse) bool {
}
}
v.lastLoc = Loc{x, y}
if usePlugin {
PostActionCall("MousePress", v, e)
}
@@ -1852,68 +1854,6 @@ func (v *View) PreviousSplit(usePlugin bool) bool {
return false
}
func (v *View) WrapBracket(usePlugin bool) bool {
if v.Cursor.HasSelection() {
lockPollEvent = true
event := screen.PollEvent()
lockPollEvent = false
ev, ok := event.(*tcell.EventKey)
if !ok {
return false
}
if !strings.Contains("()[]{}\"'", string(ev.Rune())) {
return false
}
start := v.Cursor.CurSelection[0]
end := v.Cursor.CurSelection[1]
if start.Y != end.Y {
return false
}
close := map[string]string{
")": ")",
"]": "]",
"}": "}",
"(": ")",
"[": "]",
"{": "}",
"\"": "\"",
"'": "'",
}
open := map[string]string{
")": "(",
"]": "[",
"}": "{",
"(": "(",
"[": "[",
"{": "{",
"\"": "\"",
"'": "'",
}
if usePlugin && !PreActionCall("WrapBracket", v) {
return false
}
r := string(ev.Rune())
if start.GreaterThan(end) {
start, end = end, start
v.Buf.Insert(start, open[r])
v.Buf.Insert(end.Move(1, v.Buf), close[r])
v.Cursor.CurSelection[1] = start
} else {
v.Buf.Insert(start, open[r])
v.Buf.Insert(end.Move(1, v.Buf), close[r])
v.Cursor.CurSelection[0] = start
}
if usePlugin {
return PostActionCall("WrapBracket", v)
}
}
return false
}
var curMacro []interface{}
var recordingMacro bool

View File

@@ -4,8 +4,6 @@ import (
"io/ioutil"
"os"
"strings"
"github.com/mitchellh/go-homedir"
)
var pluginCompletions []func(string) []string
@@ -22,13 +20,9 @@ func FileComplete(input string) (string, []string) {
var files []os.FileInfo
var err error
if len(dirs) > 1 {
home, _ := homedir.Dir()
directories := strings.Join(dirs[:len(dirs)-1], sep) + sep
if strings.HasPrefix(directories, "~") {
directories = strings.Replace(directories, "~", home, 1)
}
directories = ReplaceHome(directories)
files, err = ioutil.ReadDir(directories)
} else {
files, err = ioutil.ReadDir(".")
@@ -148,6 +142,55 @@ func OptionComplete(input string) (string, []string) {
return chosen, suggestions
}
func OptionValueComplete(inputOpt, input string) (string, []string) {
inputOpt = strings.TrimSpace(inputOpt)
var suggestions []string
localSettings := DefaultLocalSettings()
var optionVal interface{}
for k, option := range globalSettings {
if k == inputOpt {
optionVal = option
}
}
for k, option := range localSettings {
if k == inputOpt {
optionVal = option
}
}
switch optionVal.(type) {
case bool:
if strings.HasPrefix("on", input) {
suggestions = append(suggestions, "on")
} else if strings.HasPrefix("true", input) {
suggestions = append(suggestions, "true")
}
if strings.HasPrefix("off", input) {
suggestions = append(suggestions, "off")
} else if strings.HasPrefix("false", input) {
suggestions = append(suggestions, "false")
}
case string:
switch inputOpt {
case "colorscheme":
_, suggestions = ColorschemeComplete(input)
case "fileformat":
if strings.HasPrefix("unix", input) {
suggestions = append(suggestions, "unix")
}
if strings.HasPrefix("dos", input) {
suggestions = append(suggestions, "dos")
}
}
}
var chosen string
if len(suggestions) == 1 {
chosen = suggestions[0]
}
return chosen, suggestions
}
// MakeCompletion registers a function from a plugin for autocomplete commands
func MakeCompletion(function string) Completion {
pluginCompletions = append(pluginCompletions, LuaFunctionComplete(function))

View File

@@ -69,7 +69,6 @@ var bindingActions = map[string]func(*View, bool) bool{
"PastePrimary": (*View).PastePrimary,
"SelectAll": (*View).SelectAll,
"OpenFile": (*View).OpenFile,
"WrapBracket": (*View).WrapBracket,
"Start": (*View).Start,
"End": (*View).End,
"PageUp": (*View).PageUp,
@@ -439,7 +438,6 @@ func DefaultBindings() map[string]string {
"Down": "CursorDown",
"Right": "CursorRight",
"Left": "CursorLeft",
"Alt-j": "WrapBracket",
"ShiftUp": "SelectUp",
"ShiftDown": "SelectDown",
"ShiftLeft": "SelectLeft",

View File

@@ -2,6 +2,7 @@ package main
import (
"bytes"
"crypto/md5"
"encoding/gob"
"io"
"io/ioutil"
@@ -15,7 +16,6 @@ import (
"time"
"unicode/utf8"
"github.com/mitchellh/go-homedir"
"github.com/zyedidia/micro/cmd/micro/highlight"
)
@@ -57,6 +57,9 @@ type Buffer struct {
syntaxDef *highlight.Def
highlighter *highlight.Highlighter
// Hash of the original buffer -- empty if fastdirty is on
origHash [16]byte
// Buffer local settings
Settings map[string]interface{}
}
@@ -174,7 +177,7 @@ func NewBuffer(reader io.Reader, size int64, path string) *Buffer {
}
if b.Settings["saveundo"].(bool) {
// We should only use last time's eventhandler if the file wasn't by someone else in the meantime
// We should only use last time's eventhandler if the file wasn't modified by someone else in the meantime
if b.ModTime == buffer.ModTime {
b.EventHandler = buffer.EventHandler
b.EventHandler.buf = b
@@ -184,8 +187,13 @@ func NewBuffer(reader io.Reader, size int64, path string) *Buffer {
file.Close()
}
if b.Settings["mouse"].(bool) {
screen.EnableMouse()
if !b.Settings["fastdirty"].(bool) {
if size > 50000 {
// If the file is larger than a megabyte fastdirty needs to be on
b.Settings["fastdirty"] = true
} else {
b.origHash = md5.Sum([]byte(b.String()))
}
}
b.cursors = []*Cursor{&b.Cursor}
@@ -381,7 +389,6 @@ func (b *Buffer) Serialize() error {
// SaveAs saves the buffer to a specified path (filename), creating the file if it does not exist
func (b *Buffer) SaveAs(filename string) error {
b.UpdateRules()
dir, _ := homedir.Dir()
if b.Settings["rmtrailingws"].(bool) {
r, _ := regexp.Compile(`[ \t]+$`)
for lineNum, line := range b.Lines(0, b.NumLines) {
@@ -402,9 +409,9 @@ func (b *Buffer) SaveAs(filename string) error {
}
str := b.SaveString(b.Settings["fileformat"] == "dos")
data := []byte(str)
err := ioutil.WriteFile(filename, data, 0644)
err := ioutil.WriteFile(ReplaceHome(filename), data, 0644)
if err == nil {
b.Path = strings.Replace(filename, "~", dir, 1)
b.Path = filename
b.IsModified = false
b.ModTime, _ = GetModTime(filename)
return b.Serialize()
@@ -451,6 +458,13 @@ func (b *Buffer) SaveAsWithSudo(filename string) error {
return err
}
func (b *Buffer) Modified() bool {
if b.Settings["fastdirty"].(bool) {
return b.IsModified
}
return b.origHash != md5.Sum([]byte(b.String()))
}
func (b *Buffer) insert(pos Loc, value []byte) {
b.IsModified = true
b.LineArray.insert(pos, value)

View File

@@ -14,7 +14,6 @@ import (
"strings"
humanize "github.com/dustin/go-humanize"
"github.com/mitchellh/go-homedir"
)
// A Command contains a action (a function to call) as well as information about how to autocomplete the command
@@ -90,7 +89,7 @@ func MakeCommand(name, function string, completions ...Completion) {
// DefaultCommands returns a map containing micro's default commands
func DefaultCommands() map[string]StrCommand {
return map[string]StrCommand{
"set": {"Set", []Completion{OptionCompletion, NoCompletion}},
"set": {"Set", []Completion{OptionCompletion, OptionValueCompletion}},
"setlocal": {"SetLocal", []Completion{OptionCompletion, NoCompletion}},
"show": {"Show", []Completion{OptionCompletion, NoCompletion}},
"bind": {"Bind", []Completion{NoCompletion}},
@@ -230,8 +229,7 @@ func TabSwitch(args []string) {
// Cd changes the current working directory
func Cd(args []string) {
if len(args) > 0 {
home, _ := homedir.Dir()
path := strings.Replace(args[0], "~", home, 1)
path := ReplaceHome(args[0])
os.Chdir(path)
for _, tab := range tabs {
for _, view := range tab.views {
@@ -325,8 +323,7 @@ func VSplit(args []string) {
CurView().VSplit(NewBufferFromString("", ""))
} else {
filename := args[0]
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
filename = ReplaceHome(filename)
file, err := os.Open(filename)
fileInfo, _ := os.Stat(filename)
@@ -355,8 +352,7 @@ func HSplit(args []string) {
CurView().HSplit(NewBufferFromString("", ""))
} else {
filename := args[0]
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
filename = ReplaceHome(filename)
file, err := os.Open(filename)
fileInfo, _ := os.Stat(filename)
@@ -396,8 +392,7 @@ func NewTab(args []string) {
CurView().AddTab(true)
} else {
filename := args[0]
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
filename = ReplaceHome(filename)
file, err := os.Open(filename)
fileInfo, _ := os.Stat(filename)

View File

@@ -258,7 +258,7 @@ func (c *Cursor) UpN(amount int) {
runes := []rune(c.buf.Line(c.Y))
c.X = c.GetCharPosInLine(proposedY, c.LastVisualX)
if c.X > len(runes) {
if c.X > len(runes) || (amount < 0 && proposedY == c.Y) {
c.X = len(runes)
}

View File

@@ -231,6 +231,7 @@ const (
OptionCompletion
PluginCmdCompletion
PluginNameCompletion
OptionValueCompletion
)
// Prompt sends the user a message and waits for a response to be typed in
@@ -296,6 +297,10 @@ func (m *Messenger) Prompt(prompt, placeholder, historyType string, completionTy
chosen, suggestions = HelpComplete(currentArg)
} else if completionType == OptionCompletion {
chosen, suggestions = OptionComplete(currentArg)
} else if completionType == OptionValueCompletion {
if currentArgNum-1 > 0 {
chosen, suggestions = OptionValueComplete(args[currentArgNum-1], currentArg)
}
} else if completionType == PluginCmdCompletion {
chosen, suggestions = PluginCmdComplete(currentArg)
} else if completionType == PluginNameCompletion {

View File

@@ -59,9 +59,6 @@ var (
// Event channel
events chan tcell.Event
autosave chan bool
// Read events on another thread or wait for a temporary read
lockPollEvent bool
)
// LoadInput determines which files should be loaded into buffers
@@ -205,6 +202,10 @@ func InitScreen() {
os.Setenv("TERM", oldTerm)
}
if GetGlobalOption("mouse").(bool) {
screen.EnableMouse()
}
screen.SetStyle(defStyle)
}
@@ -253,23 +254,31 @@ func LoadAll() {
var flagVersion = flag.Bool("version", false, "Show the version number and information")
var flagStartPos = flag.String("startpos", "", "LINE,COL to start the cursor at when opening a buffer.")
var flagConfigDir = flag.String("config-dir", "", "Specify a custom location for the configuration directory")
var optionFlagSet = flag.NewFlagSet("option", flag.ExitOnError)
var flagOptions = flag.Bool("options", false, "Show all option help")
func main() {
flag.Usage = func() {
fmt.Println("Usage: micro [OPTIONS] [FILE]...")
flag.CommandLine.SetOutput(os.Stdout)
flag.PrintDefaults()
optionFlagSet.SetOutput(os.Stdout)
fmt.Print("\n------------------------------------------------------------------\n")
fmt.Print("Micro's options can also be set via command line arguments for quick\nadjustments. For real configuration, please use the bindings.json\nfile (see 'help options').\n\n")
optionFlagSet.PrintDefaults()
fmt.Println("-config-dir dir")
fmt.Println(" \tSpecify a custom location for the configuration directory")
fmt.Println("-startpos LINE,COL")
fmt.Println(" \tSpecify a line and column to start the cursor at when opening a buffer")
fmt.Println("-options")
fmt.Println(" \tShow all option help")
fmt.Println("-version")
fmt.Println(" \tShow the version number and information")
fmt.Print("\nMicro's options can also be set via command line arguments for quick\nadjustments. For real configuration, please use the bindings.json\nfile (see 'help options').\n\n")
fmt.Println("-option value")
fmt.Println(" \tSet `option` to `value` for this session")
fmt.Println(" \tFor example: `micro -syntax off file.c`")
fmt.Println("\nUse `micro -options` to see the full list of configuration options")
}
optionFlags := make(map[string]*string)
for k, v := range DefaultGlobalSettings() {
optionFlags[k] = optionFlagSet.String(k, "", fmt.Sprintf("The %s option. Default value: '%v'", k, v))
optionFlags[k] = flag.String(k, "", fmt.Sprintf("The %s option. Default value: '%v'", k, v))
}
flag.Parse()
@@ -282,6 +291,15 @@ func main() {
os.Exit(0)
}
if *flagOptions {
// If -options was passed
for k, v := range DefaultGlobalSettings() {
fmt.Printf("-%s value\n", k)
fmt.Printf(" \tThe %s option. Default value: '%v'\n", k, v)
}
os.Exit(0)
}
// Start the Lua VM for running plugins
L = lua.NewState()
defer L.Close()
@@ -422,9 +440,8 @@ func main() {
// Here is the event loop which runs in a separate thread
go func() {
for {
if screen != nil && !lockPollEvent {
if screen != nil {
events <- screen.PollEvent()
time.Sleep(1 * time.Millisecond)
}
}
}()

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,7 @@
package main
import (
"crypto/md5"
"encoding/json"
"errors"
"io/ioutil"
@@ -198,10 +199,13 @@ func DefaultGlobalSettings() map[string]interface{} {
"colorscheme": "default",
"cursorline": true,
"eofnewline": false,
"rmtrailingws": false,
"fastdirty": true,
"fileformat": "unix",
"ignorecase": false,
"indentchar": " ",
"infobar": true,
"mouse": true,
"rmtrailingws": false,
"ruler": true,
"savecursor": false,
"saveundo": false,
@@ -221,8 +225,6 @@ func DefaultGlobalSettings() map[string]interface{} {
},
"pluginrepos": []string{},
"useprimary": true,
"fileformat": "unix",
"mouse": true,
}
}
@@ -236,10 +238,12 @@ func DefaultLocalSettings() map[string]interface{} {
"colorcolumn": float64(0),
"cursorline": true,
"eofnewline": false,
"rmtrailingws": false,
"fastdirty": true,
"fileformat": "unix",
"filetype": "Unknown",
"ignorecase": false,
"indentchar": " ",
"rmtrailingws": false,
"ruler": true,
"savecursor": false,
"saveundo": false,
@@ -254,8 +258,6 @@ func DefaultLocalSettings() map[string]interface{} {
"tabsize": float64(4),
"tabstospaces": false,
"useprimary": true,
"fileformat": "unix",
"mouse": true,
}
}
@@ -315,6 +317,14 @@ func SetOption(option, value string) error {
}
}
if option == "mouse" {
if !nativeValue.(bool) {
screen.DisableMouse()
} else {
screen.EnableMouse()
}
}
if _, ok := CurView().Buf.Settings[option]; ok {
for _, tab := range tabs {
for _, view := range tab.views {
@@ -358,6 +368,26 @@ func SetLocalOption(option, value string, view *View) error {
return err
}
if option == "fastdirty" {
// If it is being turned off, we have to hash every open buffer
var empty [16]byte
for _, tab := range tabs {
for _, v := range tab.views {
if !nativeValue.(bool) {
if v.Buf.origHash == empty {
data, err := ioutil.ReadFile(v.Buf.AbsPath)
if err != nil {
data = []byte{}
}
v.Buf.origHash = md5.Sum(data)
}
} else {
v.Buf.IsModified = v.Buf.Modified()
}
}
}
}
buf.Settings[option] = nativeValue
if option == "statusline" {
@@ -382,14 +412,6 @@ func SetLocalOption(option, value string, view *View) error {
}
}
if option == "mouse" {
if !nativeValue.(bool) {
screen.DisableMouse()
} else {
screen.EnableMouse()
}
}
return nil
}

View File

@@ -20,7 +20,7 @@ func (sline *Statusline) Display() {
file := sline.view.Buf.GetName()
// If the buffer is dirty (has been modified) write a little '+'
if sline.view.Buf.IsModified {
if sline.view.Buf.Modified() {
file += " +"
}

View File

@@ -91,7 +91,7 @@ func TabbarString() (string, map[int]int) {
}
buf := t.views[t.CurView].Buf
str += buf.GetName()
if buf.IsModified {
if buf.Modified() {
str += " +"
}
if i == curTab {

View File

@@ -12,6 +12,7 @@ import (
"unicode/utf8"
"github.com/mattn/go-runewidth"
homedir "github.com/mitchellh/go-homedir"
)
// Util.go is a collection of utility functions that are used throughout
@@ -363,3 +364,18 @@ func JoinCommandArgs(args ...string) string {
return buf.String()
}
// ReplaceHome takes a path as input and replaces ~ at the start of the path with the user's
// home directory. Does nothing if the path does not start with '~'.
func ReplaceHome(path string) string {
if !strings.HasPrefix(path, "~") {
return path
}
home, err := homedir.Dir()
if err != nil {
messenger.Error("Could not find home directory: ", err)
return path
}
return strings.Replace(path, "~", home, 1)
}

View File

@@ -6,7 +6,6 @@ import (
"strings"
"time"
"github.com/mitchellh/go-homedir"
"github.com/zyedidia/tcell"
)
@@ -73,6 +72,7 @@ type View struct {
// This stores when the last click was
// This is useful for detecting double and triple clicks
lastClickTime time.Time
lastLoc Loc
// lastCutTime stores when the last ctrl+k was issued.
// It is used for clearing the clipboard to replace it with fresh cut lines.
@@ -198,7 +198,7 @@ func (v *View) ScrollDown(n int) {
// If there are unsaved changes, the user will be asked if the view can be closed
// causing them to lose the unsaved changes
func (v *View) CanClose() bool {
if v.Type == vtDefault && v.Buf.IsModified {
if v.Type == vtDefault && v.Buf.Modified() {
var choice bool
var canceled bool
if v.Buf.Settings["autosave"].(bool) {
@@ -243,8 +243,7 @@ func (v *View) OpenBuffer(buf *Buffer) {
// Open opens the given file in the view
func (v *View) Open(filename string) {
home, _ := homedir.Dir()
filename = strings.Replace(filename, "~", home, 1)
filename = ReplaceHome(filename)
file, err := os.Open(filename)
fileInfo, _ := os.Stat(filename)

View File

@@ -161,6 +161,22 @@ Here are the options that you can set:
default value: `on`
* `fileformat`: this determines what kind of line endings micro will use for the file. Unix line endings
are just `\n` (lf) whereas dos line endings are `\r\n` (crlf). The two possible values for this option
are `unix` and `dos`. The fileformat will be automatically detected and displayed on the statusline but
this option is useful if you would like to change the line endings or if you are starting a new file.
default value: `unix`
* `fastdirty`: this determines what kind of algorithm micro uses to determine if a buffer is modified or
not. When `fastdirty` is on, micro just uses a boolean `modified` that is set to `true` as soon as the user
makes an edit. This is fast, but can be inaccurate. If `fastdirty` is off, then micro will hash the current
buffer against a hash of the original file (created when the buffer was loaded). This is more accurate but
obviously more resource intensive. This option is only for people who really care about having accurate
modified status.
default value: `on`
---
Default plugin options:
@@ -179,13 +195,6 @@ Default plugin options:
default value: `on`
* `fileformat`: this determines what kind of line endings micro will use for the file. Unix line endings
are just `\n` (lf) whereas dos line endings are `\r\n` (crlf). The two possible values for this option
are `unix` and `dos`. The fileformat will be automatically detected and displayed on the statusline but
this option is useful if you would like to change the line endings or if you are starting a new file.
default value: `unix`
Any option you set in the editor will be saved to the file
~/.config/micro/settings.json so, in effect, your configuration file will be
created for you. If you'd like to take your configuration with you to another

View File

@@ -5,7 +5,7 @@ detect:
rules:
## Keywords
- keyword: "(?i)^(FROM|MAINTAINER|RUN|CMD|LABEL|EXPOSE|ENV|ADD|COPY|ENTRYPOINT|VOLUME|USER|WORKDIR|ONBUILD|ARG|HEALTHCHECK|STOPSIGNAL|SHELL)[[:space:]]"
- type.keyword: "(?i)^(FROM|MAINTAINER|RUN|CMD|LABEL|EXPOSE|ENV|ADD|COPY|ENTRYPOINT|VOLUME|USER|WORKDIR|ONBUILD|ARG|HEALTHCHECK|STOPSIGNAL|SHELL)[[:space:]]"
## Brackets & parenthesis
- statement: "(\\(|\\)|\\[|\\])"

View File

@@ -12,17 +12,18 @@ rules:
end: "$"
rules: []
# File changes
- keyword: "#[[:space:]](deleted|modified|new file|renamed):[[:space:]].*"
- keyword: "#[[:space:]]deleted:"
- keyword: "#[[:space:]]modified:"
- keyword: "#[[:space:]]new file:"
- keyword: "#[[:space:]]renamed:"
- type.keyword: "#[[:space:]](deleted|modified|new file|renamed):[[:space:]].*"
- type.keyword: "#[[:space:]]deleted:"
- type.keyword: "#[[:space:]]modified:"
- type.keyword: "#[[:space:]]new file:"
- type.keyword: "#[[:space:]]renamed:"
# Untracked filenames
- error: "^# [^/?*:;{}\\\\]+\\.[^/?*:;{}\\\\]+$"
- keyword: "^#[[:space:]]Changes.*[:]"
- keyword: "^#[[:space:]]Your branch and '[^']+"
- keyword: "^#[[:space:]]Your branch and '"
- keyword: "^#[[:space:]]On branch [^ ]+"
- keyword: "^#[[:space:]]On branch"
- type.keyword: "^#[[:space:]]Changes.*[:]"
- type.keyword: "^#[[:space:]]Your branch and '[^']+"
- type.keyword: "^#[[:space:]]Your branch and '"
- type.keyword: "^#[[:space:]]On branch [^ ]+"
- type.keyword: "^#[[:space:]]On branch"
# Recolor hash symbols
- special: "#"

View File

@@ -5,7 +5,7 @@ detect:
rules:
- constant: "\\<(true|false)\\>"
- keyword: "^[[:space:]]*[^=]*="
- type.keyword: "^[[:space:]]*[^=]*="
- constant: "^[[:space:]]*\\[.*\\]$"
- constant: "\"(\\\\.|[^\"])*\"|'(\\\\.|[^'])*'"
- comment:

View File

@@ -7,21 +7,33 @@ detect:
rules:
- type: "\\b(accept|alarm|atan2|bin(d|mode)|c(aller|h(dir|mod|op|own|root)|lose(dir)?|onnect|os|rypt)|d(bm(close|open)|efined|elete|ie|o|ump)|e(ach|of|val|x(ec|ists|it|p))|f(cntl|ileno|lock|ork))\\b|\\b(get(c|login|peername|pgrp|ppid|priority|pwnam|(host|net|proto|serv)byname|pwuid|grgid|(host|net)byaddr|protobynumber|servbyport)|([gs]et|end)(pw|gr|host|net|proto|serv)ent|getsock(name|opt)|gmtime|goto|grep|hex|index|int|ioctl|join)\\b|\\b(keys|kill|last|length|link|listen|local(time)?|log|lstat|m|mkdir|msg(ctl|get|snd|rcv)|next|oct|open(dir)?|ord|pack|pipe|pop|printf?|push|q|qq|qx|rand|re(ad(dir|link)?|cv|do|name|quire|set|turn|verse|winddir)|rindex|rmdir|s|scalar|seek(dir)?)\\b|\\b(se(lect|mctl|mget|mop|nd|tpgrp|tpriority|tsockopt)|shift|shm(ctl|get|read|write)|shutdown|sin|sleep|socket(pair)?|sort|spli(ce|t)|sprintf|sqrt|srand|stat|study|substr|symlink|sys(call|read|tem|write)|tell(dir)?|time|tr(y)?|truncate|umask)\\b|\\b(un(def|link|pack|shift)|utime|values|vec|wait(pid)?|wantarray|warn|write)\\b"
- statement: "\\b(continue|else|elsif|do|for|foreach|if|unless|until|while|eq|ne|lt|gt|le|ge|cmp|x|my|sub|use|package|can|isa)\\b"
- special: "\\-\\>"
- symbol: "(,|\\.)"
- identifier:
start: "[$@%]"
end: "((?i) |[^0-9A-Z_]|-)"
start: "[\\$@%]"
end: "\\W"
rules: []
- constant.string: "\".*\"|qq\\|.*\\|"
- constant.string: "\"\\(.*\\)\"|qq?\\|.*\\||qq?\\{.*\\}|qq?\\/.*\\/"
- default: "[sm]/.*/"
- preproc:
start: "(^use| = new)"
end: ";"
rules: []
- comment: "#.*"
- comment:
start: "#"
end: "$"
rules: []
- comment:
start: "^="
end: "^=cut"
rules: []
- identifier.macro:
start: "<< 'STOP'"
end: "STOP"
rules: []

View File

@@ -9,7 +9,7 @@ rules:
- identifier: "[a-zA-Z][_a-zA-Z0-9]*[[:space:]]*"
- statement: "\\b(assembly|break|continue|do|for|function|if|else|new|return|returns|while)\\b"
- special: "\\b(\\.send|throw)\\b" # make sure they are very visible
- keyword: "\\b(anonymous|constant|indexed|payable|public|private|external|internal)\\b"
- type.keyword: "\\b(anonymous|constant|indexed|payable|public|private|external|internal)\\b"
- constant: "\\b(block(\\.(blockhash|coinbase|difficulty|gaslimit|number|timestamp))?|msg(\\.(data|gas|sender|value))?|now|tx(\\.(gasprice|origin))?)\\b"
- constant: "\\b(keccak256|sha3|sha256|ripemd160|ecrecover|addmod|mulmod|this|super|selfdestruct|\\.balance)\\b"
- constant: "\\b(true|false)\\b"