mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-30 22:57:15 +09:00
Compare commits
197 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
be8124154b | ||
|
|
f086cc8713 | ||
|
|
624daabc02 | ||
|
|
05a187e470 | ||
|
|
53da1ff1fe | ||
|
|
112c731c7a | ||
|
|
6cf6857602 | ||
|
|
97e2fb1288 | ||
|
|
d1e70b5abf | ||
|
|
a70fb9db7d | ||
|
|
285503d009 | ||
|
|
f364965ac0 | ||
|
|
61cea4624e | ||
|
|
2899e47591 | ||
|
|
e7ee194acf | ||
|
|
6e5536eae9 | ||
|
|
5514e53a0b | ||
|
|
d8dee90c10 | ||
|
|
dcee63771a | ||
|
|
b7133b302b | ||
|
|
061040f5d9 | ||
|
|
f6ccaadc0c | ||
|
|
7c80de7ee1 | ||
|
|
ef0f506b6f | ||
|
|
3d63f0771a | ||
|
|
20ad87611f | ||
|
|
fa7839e287 | ||
|
|
2aec2c13b5 | ||
|
|
3eb0d71bd3 | ||
|
|
18f9b6f34e | ||
|
|
57110c98e4 | ||
|
|
a6ee75a9cf | ||
|
|
8d1618692e | ||
|
|
960c6cae62 | ||
|
|
67ec0d3c80 | ||
|
|
d3f32b5bc3 | ||
|
|
84e350aa6f | ||
|
|
80242f0e08 | ||
|
|
2a3ce12bd4 | ||
|
|
aed8ba105a | ||
|
|
0e9bc0ed87 | ||
|
|
9a798fe220 | ||
|
|
5c3d9db5c9 | ||
|
|
5ee774892a | ||
|
|
b4dda8bad8 | ||
|
|
47324aea97 | ||
|
|
def2b28d4e | ||
|
|
b7bc34906d | ||
|
|
bb08d5241e | ||
|
|
ab24523bff | ||
|
|
b8debb5404 | ||
|
|
d0e39853c6 | ||
|
|
a0bfd99a5d | ||
|
|
471a8b7c2b | ||
|
|
591e5e3145 | ||
|
|
282e7b1828 | ||
|
|
007b060cbd | ||
|
|
8168a75bde | ||
|
|
5afda4e76c | ||
|
|
88c712b848 | ||
|
|
fca63d02f9 | ||
|
|
330888cb3b | ||
|
|
23c24c776e | ||
|
|
233fa9b25c | ||
|
|
9530d6ad20 | ||
|
|
6458d3cac4 | ||
|
|
6945aa34eb | ||
|
|
47c9cc2fea | ||
|
|
1e90cec6f3 | ||
|
|
843867717c | ||
|
|
dd87769090 | ||
|
|
398370424b | ||
|
|
be2d3c9c1e | ||
|
|
05aa30d1be | ||
|
|
1c2b57dfe8 | ||
|
|
47ef864295 | ||
|
|
a517ea45bd | ||
|
|
342f3c223d | ||
|
|
079cbe11f4 | ||
|
|
3e61bd4d49 | ||
|
|
b517ed28c0 | ||
|
|
299712ead3 | ||
|
|
c24f75999a | ||
|
|
bde48c051a | ||
|
|
d087a890ba | ||
|
|
75d4e70560 | ||
|
|
73ab25d008 | ||
|
|
790ccd429c | ||
|
|
47fd1475b5 | ||
|
|
251a2b7455 | ||
|
|
3c85d31c15 | ||
|
|
2e6cbcb362 | ||
|
|
12d74b99e8 | ||
|
|
4cda7e2d92 | ||
|
|
1350deae56 | ||
|
|
df564e1b8b | ||
|
|
bb7ce4cbb3 | ||
|
|
1655fde09b | ||
|
|
89d1f1c202 | ||
|
|
b23c507af5 | ||
|
|
15055440da | ||
|
|
e2b7c85955 | ||
|
|
9c5ab2afbd | ||
|
|
d413562145 | ||
|
|
87f54be13a | ||
|
|
bea1c5dc28 | ||
|
|
04b4dbbfee | ||
|
|
d55e7319da | ||
|
|
54bb99d758 | ||
|
|
b977bf5cca | ||
|
|
fa7f89a400 | ||
|
|
523f75654d | ||
|
|
e85ae907a0 | ||
|
|
b0e287498e | ||
|
|
8a33c98bc6 | ||
|
|
59bf1a2260 | ||
|
|
214adcf611 | ||
|
|
23152f0c50 | ||
|
|
2a4abbee24 | ||
|
|
f637268fa7 | ||
|
|
ea7f90713c | ||
|
|
53a19afe52 | ||
|
|
ed6951a653 | ||
|
|
2e99f52133 | ||
|
|
da5542a557 | ||
|
|
1cd4b2c4dc | ||
|
|
253e86230c | ||
|
|
9f9b5def41 | ||
|
|
d949b58fc0 | ||
|
|
ab74e56a40 | ||
|
|
a537c584d0 | ||
|
|
98365b6bfb | ||
|
|
57c030d3b9 | ||
|
|
89acc703f5 | ||
|
|
6df2d7d822 | ||
|
|
3c192c2fb5 | ||
|
|
995a910f6a | ||
|
|
c29e58e3d4 | ||
|
|
924809b19b | ||
|
|
85e7055505 | ||
|
|
fb6d554df6 | ||
|
|
bd0c5c655e | ||
|
|
e6e190942c | ||
|
|
25ad139675 | ||
|
|
a095644731 | ||
|
|
f197eca320 | ||
|
|
d602cb68ca | ||
|
|
56e98ea5f4 | ||
|
|
16d8a560bf | ||
|
|
32325f99ad | ||
|
|
9b33a1058a | ||
|
|
ff5c8d7451 | ||
|
|
1ba51e4f59 | ||
|
|
7fe2b8ef2f | ||
|
|
7bb61307e0 | ||
|
|
d0057121ef | ||
|
|
18c4196354 | ||
|
|
2fcb40d5a9 | ||
|
|
0adb601f3c | ||
|
|
b669437296 | ||
|
|
9ef27203f0 | ||
|
|
d2a1d849c9 | ||
|
|
712b383e2c | ||
|
|
94175d1aa6 | ||
|
|
9b51069041 | ||
|
|
80ab81fefc | ||
|
|
d00562d37a | ||
|
|
75a344ef56 | ||
|
|
ffebb58d92 | ||
|
|
c9199ba1bd | ||
|
|
5024ecd640 | ||
|
|
a185d6f9a0 | ||
|
|
690610d4b1 | ||
|
|
043f7cdc47 | ||
|
|
4d1ad52405 | ||
|
|
7294424c3e | ||
|
|
bb55fc4150 | ||
|
|
263eec7368 | ||
|
|
7b03f5bab2 | ||
|
|
0fd042dce6 | ||
|
|
e379239140 | ||
|
|
c1db99a5a5 | ||
|
|
fb2bf7a377 | ||
|
|
9404b731ec | ||
|
|
e682c0355b | ||
|
|
d8e7291cb2 | ||
|
|
556a3eb18f | ||
|
|
f9fcdb2e8b | ||
|
|
d695d12872 | ||
|
|
ced7164912 | ||
|
|
ce3bdf63c0 | ||
|
|
4c678c4936 | ||
|
|
18d128eb3d | ||
|
|
97632e5573 | ||
|
|
a7e5a5b26c | ||
|
|
ea0dda98ce | ||
|
|
3783f0a9f0 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ binaries/
|
||||
tmp.sh
|
||||
test/
|
||||
.idea/
|
||||
packages/
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
Micro is licensed under the MIT "Expat" License:
|
||||
|
||||
Copyright (c) 2016: Zachary Yedidia.
|
||||
Copyright (c) 2016: Zachary Yedidia, et al.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
1108
LICENSE-THIRD-PARTY
Normal file
1108
LICENSE-THIRD-PARTY
Normal file
File diff suppressed because it is too large
Load Diff
15
Makefile
15
Makefile
@@ -1,11 +1,14 @@
|
||||
.PHONY: runtime
|
||||
|
||||
VERSION = $(shell go run tools/build-version.go)
|
||||
HASH = $(shell git rev-parse --short HEAD)
|
||||
DATE = $(shell go run tools/build-date.go)
|
||||
ADDITIONAL_GO_LINKER_FLAGS = $(shell go run tools/info-plist.go "$(VERSION)")
|
||||
|
||||
GOBIN ?= $(GOPATH)/bin
|
||||
VERSION := $(shell GOOS=$(shell go env GOHOSTOS) GOARCH=$(shell go env GOHOSTARCH) \
|
||||
go run tools/build-version.go)
|
||||
HASH := $(shell git rev-parse --short HEAD)
|
||||
DATE := $(shell GOOS=$(shell go env GOHOSTOS) GOARCH=$(shell go env GOHOSTARCH) \
|
||||
go run tools/build-date.go)
|
||||
ADDITIONAL_GO_LINKER_FLAGS := $(shell GOOS=$(shell go env GOHOSTOS) \
|
||||
GOARCH=$(shell go env GOHOSTARCH) \
|
||||
go run tools/info-plist.go "$(VERSION)")
|
||||
GOBIN ?= $(shell go env GOPATH)/bin
|
||||
|
||||
# Builds micro after checking dependencies but without updating the runtime
|
||||
build: deps
|
||||
|
||||
15
README.md
15
README.md
@@ -81,6 +81,12 @@ On Windows, you can install micro through Chocolatey:
|
||||
choco install micro
|
||||
```
|
||||
|
||||
On Linux, you can install micro through [snap](https://snapcraft.io/docs/core/install)
|
||||
|
||||
```
|
||||
snap install micro --beta
|
||||
```
|
||||
|
||||
### Building from source
|
||||
|
||||
If your operating system does not have a binary release, but does run Go, you can build from source.
|
||||
@@ -88,7 +94,7 @@ If your operating system does not have a binary release, but does run Go, you ca
|
||||
Make sure that you have Go version 1.5 or greater (Go 1.4 will work if your version supports CGO) and that your `GOPATH` env variable is set (I recommand setting it to `~/go` if you don't have one).
|
||||
|
||||
```
|
||||
go get -d github.com/zyedidia/micro
|
||||
go get -d github.com/zyedidia/micro/...
|
||||
cd $GOPATH/src/github.com/zyedidia/micro
|
||||
make install
|
||||
```
|
||||
@@ -97,6 +103,10 @@ The binary will then be installed to `$GOPATH/bin` (or your `$GOBIN`).
|
||||
|
||||
You can install directly with `go get` (`go get -u github.com/zyedidia/micro/cmd/micro`) but this isn't recommended because it doesn't build micro with version information which is useful for the plugin manager.
|
||||
|
||||
### MacOS terminal
|
||||
|
||||
If you are using MacOS, you should consider using [iTerm2](http://iterm2.com/) instead of the default Mac terminal. The iTerm2 terminal has much better mouse support as well as better handling of key events. The newest versions also support true color.
|
||||
|
||||
### Linux clipboard support
|
||||
|
||||
On Linux, clipboard support requires the 'xclip' or 'xsel' commands to be installed.
|
||||
@@ -164,6 +174,7 @@ a brief introduction to the more powerful configuration features micro offers.
|
||||
|
||||
If you find any bugs, please report them! I am also happy to accept pull requests from anyone.
|
||||
|
||||
You can use the [GitHub issue tracker](https://github.com/zyedidia/micro/issues) to report bugs, ask questions, or suggest new features.
|
||||
You can use the [GitHub issue tracker](https://github.com/zyedidia/micro/issues)
|
||||
to report bugs, ask questions, or suggest new features.
|
||||
|
||||
For a more informal setting to discuss the editor, you can join the [Gitter chat](https://gitter.im/zyedidia/micro).
|
||||
|
||||
@@ -111,7 +111,21 @@ func (v *View) CursorLeft(usePlugin bool) bool {
|
||||
v.Cursor.Loc = v.Cursor.CurSelection[0]
|
||||
v.Cursor.ResetSelection()
|
||||
} else {
|
||||
v.Cursor.Left()
|
||||
tabstospaces := v.Buf.Settings["tabstospaces"].(bool)
|
||||
tabmovement := v.Buf.Settings["tabmovement"].(bool)
|
||||
if tabstospaces && tabmovement {
|
||||
tabsize := int(v.Buf.Settings["tabsize"].(float64))
|
||||
line := v.Buf.Line(v.Cursor.Y)
|
||||
if v.Cursor.X-tabsize >= 0 && line[v.Cursor.X-tabsize:v.Cursor.X] == Spaces(tabsize) && IsStrWhitespace(line[0:v.Cursor.X-tabsize]) {
|
||||
for i := 0; i < tabsize; i++ {
|
||||
v.Cursor.Left()
|
||||
}
|
||||
} else {
|
||||
v.Cursor.Left()
|
||||
}
|
||||
} else {
|
||||
v.Cursor.Left()
|
||||
}
|
||||
}
|
||||
|
||||
if usePlugin {
|
||||
@@ -130,7 +144,21 @@ func (v *View) CursorRight(usePlugin bool) bool {
|
||||
v.Cursor.Loc = v.Cursor.CurSelection[1].Move(-1, v.Buf)
|
||||
v.Cursor.ResetSelection()
|
||||
} else {
|
||||
v.Cursor.Right()
|
||||
tabstospaces := v.Buf.Settings["tabstospaces"].(bool)
|
||||
tabmovement := v.Buf.Settings["tabmovement"].(bool)
|
||||
if tabstospaces && tabmovement {
|
||||
tabsize := int(v.Buf.Settings["tabsize"].(float64))
|
||||
line := v.Buf.Line(v.Cursor.Y)
|
||||
if v.Cursor.X+tabsize < Count(line) && line[v.Cursor.X:v.Cursor.X+tabsize] == Spaces(tabsize) && IsStrWhitespace(line[0:v.Cursor.X]) {
|
||||
for i := 0; i < tabsize; i++ {
|
||||
v.Cursor.Right()
|
||||
}
|
||||
} else {
|
||||
v.Cursor.Right()
|
||||
}
|
||||
} else {
|
||||
v.Cursor.Right()
|
||||
}
|
||||
}
|
||||
|
||||
if usePlugin {
|
||||
@@ -464,7 +492,7 @@ func (v *View) InsertNewline(usePlugin bool) bool {
|
||||
}
|
||||
|
||||
// Remove the whitespaces if keepautoindent setting is off
|
||||
if IsSpacesOrTabs(v.Buf.Line(v.Cursor.Y - 1)) && !v.Buf.Settings["keepautoindent"].(bool) {
|
||||
if IsSpacesOrTabs(v.Buf.Line(v.Cursor.Y-1)) && !v.Buf.Settings["keepautoindent"].(bool) {
|
||||
line := v.Buf.Line(v.Cursor.Y - 1)
|
||||
v.Buf.Remove(Loc{0, v.Cursor.Y - 1}, Loc{Count(line), v.Cursor.Y - 1})
|
||||
}
|
||||
@@ -588,14 +616,20 @@ func (v *View) IndentSelection(usePlugin bool) bool {
|
||||
}
|
||||
|
||||
if v.Cursor.HasSelection() {
|
||||
startY := v.Cursor.CurSelection[0].Y
|
||||
endY := v.Cursor.CurSelection[1].Move(-1, v.Buf).Y
|
||||
endX := v.Cursor.CurSelection[1].Move(-1, v.Buf).X
|
||||
start := v.Cursor.CurSelection[0]
|
||||
end := v.Cursor.CurSelection[1]
|
||||
if end.Y < start.Y {
|
||||
start, end = end, start
|
||||
}
|
||||
|
||||
startY := start.Y
|
||||
endY := end.Move(-1, v.Buf).Y
|
||||
endX := end.Move(-1, v.Buf).X
|
||||
for y := startY; y <= endY; y++ {
|
||||
tabsize := len(v.Buf.IndentString())
|
||||
v.Buf.Insert(Loc{0, y}, v.Buf.IndentString())
|
||||
if y == startY && v.Cursor.CurSelection[0].X > 0 {
|
||||
v.Cursor.SetSelectionStart(v.Cursor.CurSelection[0].Move(tabsize, v.Buf))
|
||||
if y == startY && start.X > 0 {
|
||||
v.Cursor.SetSelectionStart(start.Move(tabsize, v.Buf))
|
||||
}
|
||||
if y == endY {
|
||||
v.Cursor.SetSelectionEnd(Loc{endX + tabsize + 1, endY})
|
||||
@@ -643,17 +677,23 @@ func (v *View) OutdentSelection(usePlugin bool) bool {
|
||||
}
|
||||
|
||||
if v.Cursor.HasSelection() {
|
||||
startY := v.Cursor.CurSelection[0].Y
|
||||
endY := v.Cursor.CurSelection[1].Move(-1, v.Buf).Y
|
||||
endX := v.Cursor.CurSelection[1].Move(-1, v.Buf).X
|
||||
start := v.Cursor.CurSelection[0]
|
||||
end := v.Cursor.CurSelection[1]
|
||||
if end.Y < start.Y {
|
||||
start, end = end, start
|
||||
}
|
||||
|
||||
startY := start.Y
|
||||
endY := end.Move(-1, v.Buf).Y
|
||||
endX := end.Move(-1, v.Buf).X
|
||||
for y := startY; y <= endY; y++ {
|
||||
for x := 0; x < len(v.Buf.IndentString()); x++ {
|
||||
if len(GetLeadingWhitespace(v.Buf.Line(y))) == 0 {
|
||||
break
|
||||
}
|
||||
v.Buf.Remove(Loc{0, y}, Loc{1, y})
|
||||
if y == startY && v.Cursor.CurSelection[0].X > 0 {
|
||||
v.Cursor.SetSelectionStart(v.Cursor.CurSelection[0].Move(-1, v.Buf))
|
||||
if y == startY && start.X > 0 {
|
||||
v.Cursor.SetSelectionStart(start.Move(-1, v.Buf))
|
||||
}
|
||||
if y == endY {
|
||||
v.Cursor.SetSelectionEnd(Loc{endX - x, endY})
|
||||
@@ -693,39 +733,39 @@ func (v *View) InsertTab(usePlugin bool) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// SaveAll saves all open buffers
|
||||
func (v *View) SaveAll(usePlugin bool) bool {
|
||||
if usePlugin && !PreActionCall("SaveAll", v) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, t := range tabs {
|
||||
for _, v := range t.views {
|
||||
v.Save(false)
|
||||
}
|
||||
}
|
||||
|
||||
if usePlugin {
|
||||
return PostActionCall("SaveAll", v)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Save the buffer to disk
|
||||
func (v *View) Save(usePlugin bool) bool {
|
||||
if usePlugin && !PreActionCall("Save", v) {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.Type == vtHelp {
|
||||
// We can't save the help text
|
||||
if v.Type.scratch == true {
|
||||
// We can't save any view type with scratch set. eg help and log text
|
||||
return false
|
||||
}
|
||||
// If this is an empty buffer, ask for a filename
|
||||
if v.Buf.Path == "" {
|
||||
v.SaveAs(false)
|
||||
}
|
||||
err := v.Buf.Save()
|
||||
if err != nil {
|
||||
if strings.HasSuffix(err.Error(), "permission denied") {
|
||||
choice, _ := messenger.YesNoPrompt("Permission denied. Do you want to save this file using sudo? (y,n)")
|
||||
if choice {
|
||||
err = v.Buf.SaveWithSudo()
|
||||
if err != nil {
|
||||
messenger.Error(err.Error())
|
||||
return false
|
||||
}
|
||||
messenger.Message("Saved " + v.Buf.Path)
|
||||
}
|
||||
messenger.Reset()
|
||||
messenger.Clear()
|
||||
} else {
|
||||
messenger.Error(err.Error())
|
||||
}
|
||||
} else {
|
||||
messenger.Message("Saved " + v.Buf.Path)
|
||||
v.saveToFile(v.Buf.Path)
|
||||
}
|
||||
|
||||
if usePlugin {
|
||||
@@ -734,16 +774,42 @@ func (v *View) Save(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// This function saves the buffer to `filename` and changes the buffer's path and name
|
||||
// to `filename` if the save is successful
|
||||
func (v *View) saveToFile(filename string) {
|
||||
err := v.Buf.SaveAs(filename)
|
||||
if err != nil {
|
||||
if strings.HasSuffix(err.Error(), "permission denied") {
|
||||
choice, _ := messenger.YesNoPrompt("Permission denied. Do you want to save this file using sudo? (y,n)")
|
||||
if choice {
|
||||
err = v.Buf.SaveAsWithSudo(filename)
|
||||
if err != nil {
|
||||
messenger.Error(err.Error())
|
||||
} else {
|
||||
v.Buf.Path = filename
|
||||
v.Buf.name = filename
|
||||
messenger.Message("Saved " + filename)
|
||||
}
|
||||
}
|
||||
messenger.Reset()
|
||||
messenger.Clear()
|
||||
} else {
|
||||
messenger.Error(err.Error())
|
||||
}
|
||||
} else {
|
||||
v.Buf.Path = filename
|
||||
v.Buf.name = filename
|
||||
messenger.Message("Saved " + filename)
|
||||
}
|
||||
}
|
||||
|
||||
// SaveAs saves the buffer to disk with the given name
|
||||
func (v *View) SaveAs(usePlugin bool) bool {
|
||||
filename, canceled := messenger.Prompt("Filename: ", "", "Save", NoCompletion)
|
||||
if !canceled {
|
||||
// the filename might or might not be quoted, so unquote first then join the strings.
|
||||
filename = strings.Join(SplitCommandArgs(filename), " ")
|
||||
v.Buf.Path = filename
|
||||
v.Buf.name = filename
|
||||
|
||||
v.Save(true)
|
||||
v.saveToFile(filename)
|
||||
}
|
||||
|
||||
return false
|
||||
@@ -779,7 +845,7 @@ func (v *View) FindNext(usePlugin bool) bool {
|
||||
|
||||
if v.Cursor.HasSelection() {
|
||||
searchStart = ToCharPos(v.Cursor.CurSelection[1], v.Buf)
|
||||
lastSearch = v.Cursor.GetSelection()
|
||||
// lastSearch = v.Cursor.GetSelection()
|
||||
} else {
|
||||
searchStart = ToCharPos(v.Cursor.Loc, v.Buf)
|
||||
}
|
||||
@@ -1369,7 +1435,7 @@ func (v *View) CommandMode(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Escape leaves current mode / quits the editor
|
||||
// Escape leaves current mode
|
||||
func (v *View) Escape(usePlugin bool) bool {
|
||||
// check if user is searching, or the last search is still active
|
||||
if searching || lastSearch != "" {
|
||||
@@ -1381,13 +1447,11 @@ func (v *View) Escape(usePlugin bool) bool {
|
||||
messenger.Reset() // FIXME
|
||||
return true
|
||||
}
|
||||
return v.Quit(usePlugin)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Quit quits the editor
|
||||
// This behavior needs to be changed and should really only quit the editor if this
|
||||
// is the last view
|
||||
// However, since micro only supports one view for now, it doesn't really matter
|
||||
// Quit this will close the current tab or view that is open
|
||||
func (v *View) Quit(usePlugin bool) bool {
|
||||
if usePlugin && !PreActionCall("Quit", v) {
|
||||
return false
|
||||
@@ -1410,9 +1474,7 @@ func (v *View) Quit(usePlugin bool) bool {
|
||||
curTab--
|
||||
}
|
||||
if curTab == 0 {
|
||||
// CurView().Resize(screen.Size())
|
||||
CurView().ToggleTabbar()
|
||||
CurView().matches = Match(CurView())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1447,18 +1509,23 @@ func (v *View) QuitAll(usePlugin bool) bool {
|
||||
}
|
||||
|
||||
if closeAll {
|
||||
for _, tab := range tabs {
|
||||
for _, v := range tab.views {
|
||||
v.CloseBuffer()
|
||||
// only quit if all of the buffers can be closed and the user confirms that they actually want to quit everything
|
||||
shouldQuit, _ := messenger.YesNoPrompt("Do you want to quit micro (all open files will be closed)?")
|
||||
|
||||
if shouldQuit {
|
||||
for _, tab := range tabs {
|
||||
for _, v := range tab.views {
|
||||
v.CloseBuffer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if usePlugin {
|
||||
PostActionCall("QuitAll", v)
|
||||
}
|
||||
if usePlugin {
|
||||
PostActionCall("QuitAll", v)
|
||||
}
|
||||
|
||||
screen.Fini()
|
||||
os.Exit(0)
|
||||
screen.Fini()
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
@@ -1470,7 +1537,7 @@ func (v *View) AddTab(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
tab := NewTabFromView(NewView(NewBuffer(strings.NewReader(""), "")))
|
||||
tab := NewTabFromView(NewView(NewBufferFromString("", "")))
|
||||
tab.SetNum(len(tabs))
|
||||
tabs = append(tabs, tab)
|
||||
curTab = len(tabs) - 1
|
||||
@@ -1530,7 +1597,7 @@ func (v *View) VSplitBinding(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
v.VSplit(NewBuffer(strings.NewReader(""), ""))
|
||||
v.VSplit(NewBufferFromString("", ""))
|
||||
|
||||
if usePlugin {
|
||||
return PostActionCall("VSplit", v)
|
||||
@@ -1544,7 +1611,7 @@ func (v *View) HSplitBinding(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
v.HSplit(NewBuffer(strings.NewReader(""), ""))
|
||||
v.HSplit(NewBufferFromString("", ""))
|
||||
|
||||
if usePlugin {
|
||||
return PostActionCall("HSplit", v)
|
||||
|
||||
36
cmd/micro/actions_linux.go
Normal file
36
cmd/micro/actions_linux.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import "syscall"
|
||||
|
||||
// Suspend sends micro to the background. This is the same as pressing CtrlZ in most unix programs.
|
||||
// This only works on linux and has no default binding.
|
||||
// This code was adapted from the suspend code in nsf/godit
|
||||
func (v *View) Suspend(usePlugin bool) bool {
|
||||
if usePlugin && !PreActionCall("Suspend", v) {
|
||||
return false
|
||||
}
|
||||
|
||||
screenWasNil := screen == nil
|
||||
|
||||
if !screenWasNil {
|
||||
screen.Fini()
|
||||
screen = nil
|
||||
}
|
||||
|
||||
// suspend the process
|
||||
pid := syscall.Getpid()
|
||||
tid := syscall.Gettid()
|
||||
err := syscall.Tgkill(pid, tid, syscall.SIGSTOP)
|
||||
if err != nil {
|
||||
TermMessage(err)
|
||||
}
|
||||
|
||||
if !screenWasNil {
|
||||
InitScreen()
|
||||
}
|
||||
|
||||
if usePlugin {
|
||||
return PostActionCall("Suspend", v)
|
||||
}
|
||||
return true
|
||||
}
|
||||
9
cmd/micro/actions_other.go
Normal file
9
cmd/micro/actions_other.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// +build !linux
|
||||
|
||||
package main
|
||||
|
||||
func (v *View) Suspend(usePlugin bool) bool {
|
||||
messenger.Error("Suspend is only supported on Linux")
|
||||
|
||||
return false
|
||||
}
|
||||
@@ -98,6 +98,25 @@ func HelpComplete(input string) (string, []string) {
|
||||
return chosen, suggestions
|
||||
}
|
||||
|
||||
// ColorschemeComplete tab-completes names of colorschemes.
|
||||
func ColorschemeComplete(input string) (string, []string) {
|
||||
var suggestions []string
|
||||
files := ListRuntimeFiles(RTColorscheme)
|
||||
|
||||
for _, f := range files {
|
||||
if strings.HasPrefix(f.Name(), input) {
|
||||
suggestions = append(suggestions, f.Name())
|
||||
}
|
||||
}
|
||||
|
||||
var chosen string
|
||||
if len(suggestions) == 1 {
|
||||
chosen = suggestions[0]
|
||||
}
|
||||
|
||||
return chosen, suggestions
|
||||
}
|
||||
|
||||
func contains(s []string, e string) bool {
|
||||
for _, a := range s {
|
||||
if a == e {
|
||||
@@ -129,7 +148,7 @@ func OptionComplete(input string) (string, []string) {
|
||||
return chosen, suggestions
|
||||
}
|
||||
|
||||
// MakeCompletion registeres a function from a plugin for autocomplete commands
|
||||
// MakeCompletion registers a function from a plugin for autocomplete commands
|
||||
func MakeCompletion(function string) Completion {
|
||||
pluginCompletions = append(pluginCompletions, LuaFunctionComplete(function))
|
||||
return Completion(-len(pluginCompletions))
|
||||
|
||||
@@ -41,6 +41,7 @@ var bindingActions = map[string]func(*View, bool) bool{
|
||||
"Delete": (*View).Delete,
|
||||
"InsertTab": (*View).InsertTab,
|
||||
"Save": (*View).Save,
|
||||
"SaveAll": (*View).SaveAll,
|
||||
"SaveAs": (*View).SaveAs,
|
||||
"Find": (*View).Find,
|
||||
"FindNext": (*View).FindNext,
|
||||
@@ -89,6 +90,7 @@ var bindingActions = map[string]func(*View, bool) bool{
|
||||
"HSplit": (*View).HSplitBinding,
|
||||
"ToggleMacro": (*View).ToggleMacro,
|
||||
"PlayMacro": (*View).PlayMacro,
|
||||
"Suspend": (*View).Suspend,
|
||||
|
||||
// This was changed to InsertNewline but I don't want to break backwards compatibility
|
||||
"InsertEnter": (*View).InsertNewline,
|
||||
@@ -350,7 +352,7 @@ func BindKey(k, v string) {
|
||||
if helpBinding == k && v != "ToggleHelp" {
|
||||
helpBinding = ""
|
||||
}
|
||||
|
||||
|
||||
actionNames := strings.Split(v, ",")
|
||||
if actionNames[0] == "UnbindKey" {
|
||||
delete(bindings, key)
|
||||
@@ -388,7 +390,9 @@ func DefaultBindings() map[string]string {
|
||||
"CtrlLeft": "StartOfLine",
|
||||
"CtrlRight": "EndOfLine",
|
||||
"CtrlShiftLeft": "SelectToStartOfLine",
|
||||
"ShiftHome": "SelectToStartOfLine",
|
||||
"CtrlShiftRight": "SelectToEndOfLine",
|
||||
"ShiftEnd": "SelectToEndOfLine",
|
||||
"CtrlUp": "CursorStart",
|
||||
"CtrlDown": "CursorEnd",
|
||||
"CtrlShiftUp": "SelectToStart",
|
||||
@@ -414,8 +418,8 @@ func DefaultBindings() map[string]string {
|
||||
"CtrlV": "Paste",
|
||||
"CtrlA": "SelectAll",
|
||||
"CtrlT": "AddTab",
|
||||
"CtrlRightSq": "PreviousTab",
|
||||
"CtrlBackslash": "NextTab",
|
||||
"Alt,": "PreviousTab",
|
||||
"Alt.": "NextTab",
|
||||
"Home": "StartOfLine",
|
||||
"End": "EndOfLine",
|
||||
"CtrlHome": "CursorStart",
|
||||
@@ -444,6 +448,7 @@ func DefaultBindings() map[string]string {
|
||||
// Integration with file managers
|
||||
"F1": "ToggleHelp",
|
||||
"F2": "Save",
|
||||
"F3": "Find",
|
||||
"F4": "Quit",
|
||||
"F7": "Find",
|
||||
"F10": "Quit",
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/zyedidia/micro/cmd/micro/highlight"
|
||||
)
|
||||
|
||||
// Buffer stores the text for files that are loaded into the text editor
|
||||
@@ -44,8 +45,8 @@ type Buffer struct {
|
||||
|
||||
NumLines int
|
||||
|
||||
// Syntax highlighting rules
|
||||
rules []SyntaxRule
|
||||
syntaxDef *highlight.Def
|
||||
highlighter *highlight.Highlighter
|
||||
|
||||
// Buffer local settings
|
||||
Settings map[string]interface{}
|
||||
@@ -60,11 +61,11 @@ type SerializedBuffer struct {
|
||||
}
|
||||
|
||||
func NewBufferFromString(text, path string) *Buffer {
|
||||
return NewBuffer(strings.NewReader(text), path)
|
||||
return NewBuffer(strings.NewReader(text), int64(len(text)), path)
|
||||
}
|
||||
|
||||
// NewBuffer creates a new buffer from a given reader with a given path
|
||||
func NewBuffer(reader io.Reader, path string) *Buffer {
|
||||
func NewBuffer(reader io.Reader, size int64, path string) *Buffer {
|
||||
if path != "" {
|
||||
for _, tab := range tabs {
|
||||
for _, view := range tab.views {
|
||||
@@ -76,7 +77,7 @@ func NewBuffer(reader io.Reader, path string) *Buffer {
|
||||
}
|
||||
|
||||
b := new(Buffer)
|
||||
b.LineArray = NewLineArray(reader)
|
||||
b.LineArray = NewLineArray(size, reader)
|
||||
|
||||
b.Settings = DefaultLocalSettings()
|
||||
for k, v := range globalSettings {
|
||||
@@ -96,7 +97,6 @@ func NewBuffer(reader io.Reader, path string) *Buffer {
|
||||
b.EventHandler = NewEventHandler(b)
|
||||
|
||||
b.Update()
|
||||
b.FindFileType()
|
||||
b.UpdateRules()
|
||||
|
||||
if _, err := os.Stat(configDir + "/buffers/"); os.IsNotExist(err) {
|
||||
@@ -185,12 +185,68 @@ func (b *Buffer) GetName() string {
|
||||
// UpdateRules updates the syntax rules and filetype for this buffer
|
||||
// This is called when the colorscheme changes
|
||||
func (b *Buffer) UpdateRules() {
|
||||
b.rules = GetRules(b)
|
||||
}
|
||||
rehighlight := false
|
||||
var files []*highlight.File
|
||||
for _, f := range ListRuntimeFiles(RTSyntax) {
|
||||
data, err := f.Data()
|
||||
if err != nil {
|
||||
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
|
||||
} else {
|
||||
file, err := highlight.ParseFile(data)
|
||||
if err != nil {
|
||||
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
|
||||
continue
|
||||
}
|
||||
ftdetect, err := highlight.ParseFtDetect(file)
|
||||
if err != nil {
|
||||
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
// FindFileType identifies this buffer's filetype based on the extension or header
|
||||
func (b *Buffer) FindFileType() {
|
||||
b.Settings["filetype"] = FindFileType(b)
|
||||
ft := b.Settings["filetype"].(string)
|
||||
if ft == "Unknown" || ft == "" {
|
||||
if highlight.MatchFiletype(ftdetect, b.Path, b.lines[0].data) {
|
||||
header := new(highlight.Header)
|
||||
header.FileType = file.FileType
|
||||
header.FtDetect = ftdetect
|
||||
b.syntaxDef, err = highlight.ParseDef(file, header)
|
||||
if err != nil {
|
||||
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
|
||||
continue
|
||||
}
|
||||
rehighlight = true
|
||||
}
|
||||
} else {
|
||||
if file.FileType == ft {
|
||||
header := new(highlight.Header)
|
||||
header.FileType = file.FileType
|
||||
header.FtDetect = ftdetect
|
||||
b.syntaxDef, err = highlight.ParseDef(file, header)
|
||||
if err != nil {
|
||||
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
|
||||
continue
|
||||
}
|
||||
rehighlight = true
|
||||
}
|
||||
}
|
||||
files = append(files, file)
|
||||
}
|
||||
}
|
||||
|
||||
if b.syntaxDef != nil {
|
||||
highlight.ResolveIncludes(b.syntaxDef, files)
|
||||
}
|
||||
files = nil
|
||||
|
||||
if b.highlighter == nil || rehighlight {
|
||||
if b.syntaxDef != nil {
|
||||
b.Settings["filetype"] = b.syntaxDef.FileType
|
||||
b.highlighter = highlight.NewHighlighter(b.syntaxDef)
|
||||
if b.Settings["syntax"].(bool) {
|
||||
b.highlighter.HighlightStates(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FileType returns the buffer's filetype
|
||||
@@ -280,10 +336,8 @@ 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.FindFileType()
|
||||
b.UpdateRules()
|
||||
dir, _ := homedir.Dir()
|
||||
b.Path = strings.Replace(filename, "~", dir, 1)
|
||||
if b.Settings["rmtrailingws"].(bool) {
|
||||
r, _ := regexp.Compile(`[ \t]+$`)
|
||||
for lineNum, line := range b.Lines(0, b.NumLines) {
|
||||
@@ -306,6 +360,7 @@ func (b *Buffer) SaveAs(filename string) error {
|
||||
data := []byte(str)
|
||||
err := ioutil.WriteFile(filename, data, 0644)
|
||||
if err == nil {
|
||||
b.Path = strings.Replace(filename, "~", dir, 1)
|
||||
b.IsModified = false
|
||||
b.ModTime, _ = GetModTime(filename)
|
||||
return b.Serialize()
|
||||
@@ -317,7 +372,6 @@ func (b *Buffer) SaveAs(filename string) error {
|
||||
// SaveAsWithSudo is the same as SaveAs except it uses a neat trick
|
||||
// with tee to use sudo so the user doesn't have to reopen micro with sudo
|
||||
func (b *Buffer) SaveAsWithSudo(filename string) error {
|
||||
b.FindFileType()
|
||||
b.UpdateRules()
|
||||
b.Path = filename
|
||||
|
||||
@@ -388,7 +442,7 @@ func (b *Buffer) Start() Loc {
|
||||
|
||||
// End returns the location of the last character in the buffer
|
||||
func (b *Buffer) End() Loc {
|
||||
return Loc{utf8.RuneCount(b.lines[b.NumLines-1]), b.NumLines - 1}
|
||||
return Loc{utf8.RuneCount(b.lines[b.NumLines-1].data), b.NumLines - 1}
|
||||
}
|
||||
|
||||
// RuneAt returns the rune at a given location in the buffer
|
||||
@@ -405,7 +459,11 @@ func (b *Buffer) Line(n int) string {
|
||||
if n >= len(b.lines) {
|
||||
return ""
|
||||
}
|
||||
return string(b.lines[n])
|
||||
return string(b.lines[n].data)
|
||||
}
|
||||
|
||||
func (b *Buffer) LinesNum() int {
|
||||
return len(b.lines)
|
||||
}
|
||||
|
||||
// Lines returns an array of strings containing the lines from start to end
|
||||
@@ -413,7 +471,7 @@ func (b *Buffer) Lines(start, end int) []string {
|
||||
lines := b.lines[start:end]
|
||||
var slice []string
|
||||
for _, line := range lines {
|
||||
slice = append(slice, string(line))
|
||||
slice = append(slice, string(line.data))
|
||||
}
|
||||
return slice
|
||||
}
|
||||
@@ -432,7 +490,7 @@ func (b *Buffer) MoveLinesUp(start int, end int) {
|
||||
if end == len(b.lines) {
|
||||
b.Insert(
|
||||
Loc{
|
||||
utf8.RuneCount(b.lines[end-1]),
|
||||
utf8.RuneCount(b.lines[end-1].data),
|
||||
end - 1,
|
||||
},
|
||||
"\n"+b.Line(start-1),
|
||||
@@ -467,3 +525,11 @@ func (b *Buffer) MoveLinesDown(start int, end int) {
|
||||
Loc{0, end + 1},
|
||||
)
|
||||
}
|
||||
|
||||
// ClearMatches clears all of the syntax highlighting for this buffer
|
||||
func (b *Buffer) ClearMatches() {
|
||||
for i := range b.lines {
|
||||
b.SetMatch(i, nil)
|
||||
b.SetState(i, nil)
|
||||
}
|
||||
}
|
||||
|
||||
207
cmd/micro/cellview.go
Normal file
207
cmd/micro/cellview.go
Normal file
@@ -0,0 +1,207 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattn/go-runewidth"
|
||||
"github.com/zyedidia/tcell"
|
||||
)
|
||||
|
||||
func min(a, b int) int {
|
||||
if a <= b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func visualToCharPos(visualIndex int, lineN int, str string, buf *Buffer, tabsize int) (int, int, *tcell.Style) {
|
||||
charPos := 0
|
||||
var lineIdx int
|
||||
var lastWidth int
|
||||
var style *tcell.Style
|
||||
var width int
|
||||
var rw int
|
||||
for i, c := range str {
|
||||
// width := StringWidth(str[:i], tabsize)
|
||||
|
||||
if group, ok := buf.Match(lineN)[charPos]; ok {
|
||||
s := GetColor(group.String())
|
||||
style = &s
|
||||
}
|
||||
|
||||
if width >= visualIndex {
|
||||
return charPos, visualIndex - lastWidth, style
|
||||
}
|
||||
|
||||
if i != 0 {
|
||||
charPos++
|
||||
lineIdx += rw
|
||||
}
|
||||
lastWidth = width
|
||||
rw = 0
|
||||
if c == '\t' {
|
||||
rw = tabsize - (lineIdx % tabsize)
|
||||
width += rw
|
||||
} else {
|
||||
rw = runewidth.RuneWidth(c)
|
||||
width += rw
|
||||
}
|
||||
}
|
||||
|
||||
return -1, -1, style
|
||||
}
|
||||
|
||||
type Char struct {
|
||||
visualLoc Loc
|
||||
realLoc Loc
|
||||
char rune
|
||||
// The actual character that is drawn
|
||||
// This is only different from char if it's for example hidden character
|
||||
drawChar rune
|
||||
style tcell.Style
|
||||
width int
|
||||
}
|
||||
|
||||
type CellView struct {
|
||||
lines [][]*Char
|
||||
}
|
||||
|
||||
func (c *CellView) Draw(buf *Buffer, top, height, left, width int) {
|
||||
tabsize := int(buf.Settings["tabsize"].(float64))
|
||||
softwrap := buf.Settings["softwrap"].(bool)
|
||||
indentrunes := []rune(buf.Settings["indentchar"].(string))
|
||||
// if empty indentchar settings, use space
|
||||
if indentrunes == nil || len(indentrunes) == 0 {
|
||||
indentrunes = []rune(" ")
|
||||
}
|
||||
indentchar := indentrunes[0]
|
||||
|
||||
start := buf.Cursor.Y
|
||||
if buf.Settings["syntax"].(bool) && buf.syntaxDef != nil {
|
||||
if start > 0 && buf.lines[start-1].rehighlight {
|
||||
buf.highlighter.ReHighlightLine(buf, start-1)
|
||||
buf.lines[start-1].rehighlight = false
|
||||
}
|
||||
|
||||
buf.highlighter.ReHighlightStates(buf, start)
|
||||
|
||||
buf.highlighter.HighlightMatches(buf, top, top+height)
|
||||
}
|
||||
|
||||
c.lines = make([][]*Char, 0)
|
||||
|
||||
viewLine := 0
|
||||
lineN := top
|
||||
|
||||
curStyle := defStyle
|
||||
for viewLine < height {
|
||||
if lineN >= len(buf.lines) {
|
||||
break
|
||||
}
|
||||
|
||||
lineStr := buf.Line(lineN)
|
||||
line := []rune(lineStr)
|
||||
|
||||
colN, startOffset, startStyle := visualToCharPos(left, lineN, lineStr, buf, tabsize)
|
||||
if colN < 0 {
|
||||
colN = len(line)
|
||||
}
|
||||
viewCol := -startOffset
|
||||
if startStyle != nil {
|
||||
curStyle = *startStyle
|
||||
}
|
||||
|
||||
// We'll either draw the length of the line, or the width of the screen
|
||||
// whichever is smaller
|
||||
lineLength := min(StringWidth(lineStr, tabsize), width)
|
||||
c.lines = append(c.lines, make([]*Char, lineLength))
|
||||
|
||||
wrap := false
|
||||
// We only need to wrap if the length of the line is greater than the width of the terminal screen
|
||||
if softwrap && StringWidth(lineStr, tabsize) > width {
|
||||
wrap = true
|
||||
// We're going to draw the entire line now
|
||||
lineLength = StringWidth(lineStr, tabsize)
|
||||
}
|
||||
|
||||
for viewCol < lineLength {
|
||||
if colN >= len(line) {
|
||||
break
|
||||
}
|
||||
if group, ok := buf.Match(lineN)[colN]; ok {
|
||||
curStyle = GetColor(group.String())
|
||||
}
|
||||
|
||||
char := line[colN]
|
||||
|
||||
if viewCol >= 0 {
|
||||
c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, char, curStyle, 1}
|
||||
}
|
||||
if char == '\t' {
|
||||
charWidth := tabsize - (viewCol+left)%tabsize
|
||||
if viewCol >= 0 {
|
||||
c.lines[viewLine][viewCol].drawChar = indentchar
|
||||
c.lines[viewLine][viewCol].width = charWidth
|
||||
|
||||
indentStyle := curStyle
|
||||
if group, ok := colorscheme["indent-char"]; ok {
|
||||
indentStyle = group
|
||||
}
|
||||
|
||||
c.lines[viewLine][viewCol].style = indentStyle
|
||||
}
|
||||
|
||||
for i := 1; i < charWidth; i++ {
|
||||
viewCol++
|
||||
if viewCol >= 0 && viewCol < lineLength {
|
||||
c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
|
||||
}
|
||||
}
|
||||
viewCol++
|
||||
} else if runewidth.RuneWidth(char) > 1 {
|
||||
charWidth := runewidth.RuneWidth(char)
|
||||
if viewCol >= 0 {
|
||||
c.lines[viewLine][viewCol].width = charWidth
|
||||
}
|
||||
for i := 1; i < charWidth; i++ {
|
||||
viewCol++
|
||||
if viewCol >= 0 && viewCol < lineLength {
|
||||
c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
|
||||
}
|
||||
}
|
||||
viewCol++
|
||||
} else {
|
||||
viewCol++
|
||||
}
|
||||
colN++
|
||||
|
||||
if wrap && viewCol >= width {
|
||||
viewLine++
|
||||
|
||||
// If we go too far soft wrapping we have to cut off
|
||||
if viewLine >= height {
|
||||
break
|
||||
}
|
||||
|
||||
nextLine := line[colN:]
|
||||
lineLength := min(StringWidth(string(nextLine), tabsize), width)
|
||||
c.lines = append(c.lines, make([]*Char, lineLength))
|
||||
|
||||
viewCol = 0
|
||||
}
|
||||
|
||||
}
|
||||
if group, ok := buf.Match(lineN)[len(line)]; ok {
|
||||
curStyle = GetColor(group.String())
|
||||
}
|
||||
|
||||
// newline
|
||||
viewLine++
|
||||
lineN++
|
||||
}
|
||||
|
||||
for i := top; i < top+height; i++ {
|
||||
if i >= buf.NumLines {
|
||||
break
|
||||
}
|
||||
buf.SetMatch(i, nil)
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,33 @@ type Colorscheme map[string]tcell.Style
|
||||
// The current colorscheme
|
||||
var colorscheme Colorscheme
|
||||
|
||||
// This takes in a syntax group and returns the colorscheme's style for that group
|
||||
func GetColor(color string) tcell.Style {
|
||||
st := defStyle
|
||||
if color == "" {
|
||||
return st
|
||||
}
|
||||
groups := strings.Split(color, ".")
|
||||
if len(groups) > 1 {
|
||||
curGroup := ""
|
||||
for i, g := range groups {
|
||||
if i != 0 {
|
||||
curGroup += "."
|
||||
}
|
||||
curGroup += g
|
||||
if style, ok := colorscheme[curGroup]; ok {
|
||||
st = style
|
||||
}
|
||||
}
|
||||
} else if style, ok := colorscheme[color]; ok {
|
||||
st = style
|
||||
} else {
|
||||
st = StringToStyle(color)
|
||||
}
|
||||
|
||||
return st
|
||||
}
|
||||
|
||||
// ColorschemeExists checks if a given colorscheme exists
|
||||
func ColorschemeExists(colorschemeName string) bool {
|
||||
return FindRuntimeFile(RTColorscheme, colorschemeName) != nil
|
||||
@@ -23,10 +50,11 @@ func ColorschemeExists(colorschemeName string) bool {
|
||||
// InitColorscheme picks and initializes the colorscheme when micro starts
|
||||
func InitColorscheme() {
|
||||
colorscheme = make(Colorscheme)
|
||||
defStyle = tcell.StyleDefault.
|
||||
Foreground(tcell.ColorDefault).
|
||||
Background(tcell.ColorDefault)
|
||||
if screen != nil {
|
||||
screen.SetStyle(tcell.StyleDefault.
|
||||
Foreground(tcell.ColorDefault).
|
||||
Background(tcell.ColorDefault))
|
||||
screen.SetStyle(defStyle)
|
||||
}
|
||||
|
||||
LoadDefaultColorscheme()
|
||||
@@ -47,20 +75,6 @@ func LoadColorscheme(colorschemeName string) {
|
||||
TermMessage("Error loading colorscheme:", err)
|
||||
} else {
|
||||
colorscheme = ParseColorscheme(string(data))
|
||||
|
||||
// Default style
|
||||
defStyle = tcell.StyleDefault.
|
||||
Foreground(tcell.ColorDefault).
|
||||
Background(tcell.ColorDefault)
|
||||
|
||||
// There may be another default style defined in the colorscheme
|
||||
// In that case we should use that one
|
||||
if style, ok := colorscheme["default"]; ok {
|
||||
defStyle = style
|
||||
}
|
||||
if screen != nil {
|
||||
screen.SetStyle(defStyle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,6 +108,9 @@ func ParseColorscheme(text string) Colorscheme {
|
||||
if link == "default" {
|
||||
defStyle = style
|
||||
}
|
||||
if screen != nil {
|
||||
screen.SetStyle(defStyle)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("Color-link statement is not valid:", line)
|
||||
}
|
||||
@@ -107,7 +124,13 @@ func ParseColorscheme(text string) Colorscheme {
|
||||
// The 'extra' can be bold, reverse, or underline
|
||||
func StringToStyle(str string) tcell.Style {
|
||||
var fg, bg string
|
||||
split := strings.Split(str, ",")
|
||||
spaceSplit := strings.Split(str, " ")
|
||||
var split []string
|
||||
if len(spaceSplit) > 1 {
|
||||
split = strings.Split(spaceSplit[1], ",")
|
||||
} else {
|
||||
split = strings.Split(str, ",")
|
||||
}
|
||||
if len(split) > 1 {
|
||||
fg, bg = split[0], split[1]
|
||||
} else {
|
||||
|
||||
@@ -9,16 +9,21 @@ import (
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"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
|
||||
type Command struct {
|
||||
action func([]string)
|
||||
completions []Completion
|
||||
}
|
||||
|
||||
// A StrCommand is similar to a command but keeps the name of the action
|
||||
type StrCommand struct {
|
||||
action string
|
||||
completions []Completion
|
||||
@@ -49,6 +54,8 @@ func init() {
|
||||
"Cd": Cd,
|
||||
"Pwd": Pwd,
|
||||
"Open": Open,
|
||||
"TabSwitch": TabSwitch,
|
||||
"MemUsage": MemUsage,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,25 +89,27 @@ 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}},
|
||||
"setlocal": {"SetLocal", []Completion{OptionCompletion, NoCompletion}},
|
||||
"show": {"Show", []Completion{OptionCompletion, NoCompletion}},
|
||||
"bind": {"Bind", []Completion{NoCompletion}},
|
||||
"run": {"Run", []Completion{NoCompletion}},
|
||||
"quit": {"Quit", []Completion{NoCompletion}},
|
||||
"save": {"Save", []Completion{NoCompletion}},
|
||||
"replace": {"Replace", []Completion{NoCompletion}},
|
||||
"vsplit": {"VSplit", []Completion{FileCompletion, NoCompletion}},
|
||||
"hsplit": {"HSplit", []Completion{FileCompletion, NoCompletion}},
|
||||
"tab": {"Tab", []Completion{FileCompletion, NoCompletion}},
|
||||
"help": {"Help", []Completion{HelpCompletion, NoCompletion}},
|
||||
"eval": {"Eval", []Completion{NoCompletion}},
|
||||
"log": {"ToggleLog", []Completion{NoCompletion}},
|
||||
"plugin": {"Plugin", []Completion{PluginCmdCompletion, PluginNameCompletion}},
|
||||
"reload": {"Reload", []Completion{NoCompletion}},
|
||||
"cd": {"Cd", []Completion{FileCompletion}},
|
||||
"pwd": {"Pwd", []Completion{NoCompletion}},
|
||||
"open": {"Open", []Completion{FileCompletion}},
|
||||
"set": {"Set", []Completion{OptionCompletion, NoCompletion}},
|
||||
"setlocal": {"SetLocal", []Completion{OptionCompletion, NoCompletion}},
|
||||
"show": {"Show", []Completion{OptionCompletion, NoCompletion}},
|
||||
"bind": {"Bind", []Completion{NoCompletion}},
|
||||
"run": {"Run", []Completion{NoCompletion}},
|
||||
"quit": {"Quit", []Completion{NoCompletion}},
|
||||
"save": {"Save", []Completion{NoCompletion}},
|
||||
"replace": {"Replace", []Completion{NoCompletion}},
|
||||
"vsplit": {"VSplit", []Completion{FileCompletion, NoCompletion}},
|
||||
"hsplit": {"HSplit", []Completion{FileCompletion, NoCompletion}},
|
||||
"tab": {"Tab", []Completion{FileCompletion, NoCompletion}},
|
||||
"help": {"Help", []Completion{HelpCompletion, NoCompletion}},
|
||||
"eval": {"Eval", []Completion{NoCompletion}},
|
||||
"log": {"ToggleLog", []Completion{NoCompletion}},
|
||||
"plugin": {"Plugin", []Completion{PluginCmdCompletion, PluginNameCompletion}},
|
||||
"reload": {"Reload", []Completion{NoCompletion}},
|
||||
"cd": {"Cd", []Completion{FileCompletion}},
|
||||
"pwd": {"Pwd", []Completion{NoCompletion}},
|
||||
"open": {"Open", []Completion{FileCompletion}},
|
||||
"tabswitch": {"TabSwitch", []Completion{NoCompletion}},
|
||||
"memusage": {"MemUsage", []Completion{NoCompletion}},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +196,36 @@ func PluginCmd(args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
// TabSwitch switches to a given tab either by name or by number
|
||||
func TabSwitch(args []string) {
|
||||
if len(args) > 0 {
|
||||
num, err := strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
// Check for tab with this name
|
||||
|
||||
found := false
|
||||
for _, t := range tabs {
|
||||
v := t.views[t.CurView]
|
||||
if v.Buf.GetName() == args[0] {
|
||||
curTab = v.TabNum
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
messenger.Error("Could not find tab: ", err)
|
||||
}
|
||||
} else {
|
||||
num--
|
||||
if num >= 0 && num < len(tabs) {
|
||||
curTab = num
|
||||
} else {
|
||||
messenger.Error("Invalid tab index")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cd changes the current working directory
|
||||
func Cd(args []string) {
|
||||
if len(args) > 0 {
|
||||
home, _ := homedir.Dir()
|
||||
@@ -204,6 +243,21 @@ func Cd(args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
// MemUsage prints micro's memory usage
|
||||
// Alloc shows how many bytes are currently in use
|
||||
// Sys shows how many bytes have been requested from the operating system
|
||||
// NumGC shows how many times the GC has been run
|
||||
// Note that Go commonly reserves more memory from the OS than is currently in-use/required
|
||||
// Additionally, even if Go returns memory to the OS, the OS does not always claim it because
|
||||
// there may be plenty of memory to spare
|
||||
func MemUsage(args []string) {
|
||||
var mem runtime.MemStats
|
||||
runtime.ReadMemStats(&mem)
|
||||
|
||||
messenger.Message(fmt.Sprintf("Alloc: %v, Sys: %v, NumGC: %v", humanize.Bytes(mem.Alloc), humanize.Bytes(mem.Sys), mem.NumGC))
|
||||
}
|
||||
|
||||
// Pwd prints the current working directory
|
||||
func Pwd(args []string) {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
@@ -213,6 +267,7 @@ func Pwd(args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Open opens a new buffer with a given filename
|
||||
func Open(args []string) {
|
||||
if len(args) > 0 {
|
||||
filename := args[0]
|
||||
@@ -225,6 +280,7 @@ func Open(args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
// ToggleLog toggles the log view
|
||||
func ToggleLog(args []string) {
|
||||
buffer := messenger.getBuffer()
|
||||
if CurView().Type != vtLog {
|
||||
@@ -240,6 +296,7 @@ func ToggleLog(args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Reload reloads all files (syntax files, colorschemes...)
|
||||
func Reload(args []string) {
|
||||
LoadAll()
|
||||
}
|
||||
@@ -263,20 +320,27 @@ func Help(args []string) {
|
||||
// If no file is given, it opens an empty buffer in a new split
|
||||
func VSplit(args []string) {
|
||||
if len(args) == 0 {
|
||||
CurView().VSplit(NewBuffer(strings.NewReader(""), ""))
|
||||
CurView().VSplit(NewBufferFromString("", ""))
|
||||
} else {
|
||||
filename := args[0]
|
||||
home, _ := homedir.Dir()
|
||||
filename = strings.Replace(filename, "~", home, 1)
|
||||
file, err := os.Open(filename)
|
||||
fileInfo, _ := os.Stat(filename)
|
||||
|
||||
if err == nil && fileInfo.IsDir() {
|
||||
messenger.Error(filename, " is a directory")
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
var buf *Buffer
|
||||
if err != nil {
|
||||
// File does not exist -- create an empty buffer with that name
|
||||
buf = NewBuffer(strings.NewReader(""), filename)
|
||||
buf = NewBufferFromString("", filename)
|
||||
} else {
|
||||
buf = NewBuffer(file, filename)
|
||||
buf = NewBuffer(file, FSize(file), filename)
|
||||
}
|
||||
CurView().VSplit(buf)
|
||||
}
|
||||
@@ -286,20 +350,27 @@ func VSplit(args []string) {
|
||||
// If no file is given, it opens an empty buffer in a new split
|
||||
func HSplit(args []string) {
|
||||
if len(args) == 0 {
|
||||
CurView().HSplit(NewBuffer(strings.NewReader(""), ""))
|
||||
CurView().HSplit(NewBufferFromString("", ""))
|
||||
} else {
|
||||
filename := args[0]
|
||||
home, _ := homedir.Dir()
|
||||
filename = strings.Replace(filename, "~", home, 1)
|
||||
file, err := os.Open(filename)
|
||||
fileInfo, _ := os.Stat(filename)
|
||||
|
||||
if err == nil && fileInfo.IsDir() {
|
||||
messenger.Error(filename, " is a directory")
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
var buf *Buffer
|
||||
if err != nil {
|
||||
// File does not exist -- create an empty buffer with that name
|
||||
buf = NewBuffer(strings.NewReader(""), filename)
|
||||
buf = NewBufferFromString("", filename)
|
||||
} else {
|
||||
buf = NewBuffer(file, filename)
|
||||
buf = NewBuffer(file, FSize(file), filename)
|
||||
}
|
||||
CurView().HSplit(buf)
|
||||
}
|
||||
@@ -325,10 +396,24 @@ func NewTab(args []string) {
|
||||
filename := args[0]
|
||||
home, _ := homedir.Dir()
|
||||
filename = strings.Replace(filename, "~", home, 1)
|
||||
file, _ := os.Open(filename)
|
||||
file, err := os.Open(filename)
|
||||
fileInfo, _ := os.Stat(filename)
|
||||
|
||||
if err == nil && fileInfo.IsDir() {
|
||||
messenger.Error(filename, " is a directory")
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
tab := NewTabFromView(NewView(NewBuffer(file, filename)))
|
||||
var buf *Buffer
|
||||
if err != nil {
|
||||
buf = NewBufferFromString("", filename)
|
||||
} else {
|
||||
buf = NewBuffer(file, FSize(file), filename)
|
||||
}
|
||||
|
||||
tab := NewTabFromView(NewView(buf))
|
||||
tab.SetNum(len(tabs))
|
||||
tabs = append(tabs, tab)
|
||||
curTab = len(tabs) - 1
|
||||
@@ -349,8 +434,8 @@ func Set(args []string) {
|
||||
return
|
||||
}
|
||||
|
||||
option := strings.TrimSpace(args[0])
|
||||
value := strings.TrimSpace(args[1])
|
||||
option := args[0]
|
||||
value := args[1]
|
||||
|
||||
SetOptionAndSettings(option, value)
|
||||
}
|
||||
@@ -362,8 +447,8 @@ func SetLocal(args []string) {
|
||||
return
|
||||
}
|
||||
|
||||
option := strings.TrimSpace(args[0])
|
||||
value := strings.TrimSpace(args[1])
|
||||
option := args[0]
|
||||
value := args[1]
|
||||
|
||||
err := SetLocalOption(option, value, CurView())
|
||||
if err != nil {
|
||||
@@ -454,9 +539,6 @@ func Replace(args []string) {
|
||||
break
|
||||
}
|
||||
view.Relocate()
|
||||
if view.Buf.Settings["syntax"].(bool) {
|
||||
view.matches = Match(view)
|
||||
}
|
||||
RedrawAll()
|
||||
choice, canceled := messenger.YesNoPrompt("Perform replacement? (y,n)")
|
||||
if canceled {
|
||||
@@ -483,28 +565,25 @@ func Replace(args []string) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bufStr := view.Buf.String()
|
||||
matches := regex.FindAllStringIndex(bufStr, -1)
|
||||
if matches != nil && len(matches) > 0 {
|
||||
prevMatchCount := runePos(matches[0][0], bufStr)
|
||||
searchCount := runePos(matches[0][1], bufStr) - prevMatchCount
|
||||
from := FromCharPos(matches[0][0], view.Buf)
|
||||
to := from.Move(searchCount, view.Buf)
|
||||
adjust := Count(replace) - searchCount
|
||||
view.Buf.Replace(from, to, replace)
|
||||
if len(matches) > 1 {
|
||||
for _, match := range matches[1:] {
|
||||
found++
|
||||
matchCount := runePos(match[0], bufStr)
|
||||
searchCount = runePos(match[1], bufStr) - matchCount
|
||||
from = from.Move(matchCount-prevMatchCount+adjust, view.Buf)
|
||||
to = from.Move(searchCount, view.Buf)
|
||||
// var deltas []Delta
|
||||
for i := 0; i < view.Buf.LinesNum(); i++ {
|
||||
// view.Buf.lines[i].data = regex.ReplaceAll(view.Buf.lines[i].data, []byte(replace))
|
||||
for {
|
||||
m := regex.FindIndex(view.Buf.lines[i].data)
|
||||
|
||||
if m != nil {
|
||||
from := Loc{m[0], i}
|
||||
to := Loc{m[1], i}
|
||||
|
||||
// deltas = append(deltas, Delta{replace, from, to})
|
||||
view.Buf.Replace(from, to, replace)
|
||||
prevMatchCount = matchCount
|
||||
adjust = Count(replace) - searchCount
|
||||
found++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// view.Buf.MultipleReplace(deltas)
|
||||
}
|
||||
view.Cursor.Relocate()
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ const (
|
||||
TextEventInsert = 1
|
||||
// TextEventRemove represents a deletion event
|
||||
TextEventRemove = -1
|
||||
|
||||
TextEventReplace = 0
|
||||
)
|
||||
|
||||
// TextEvent holds data for a manipulation on some text that can be undone
|
||||
@@ -22,18 +24,31 @@ type TextEvent struct {
|
||||
C Cursor
|
||||
|
||||
EventType int
|
||||
Text string
|
||||
Start Loc
|
||||
End Loc
|
||||
Deltas []Delta
|
||||
Time time.Time
|
||||
}
|
||||
|
||||
type Delta struct {
|
||||
Text string
|
||||
Start Loc
|
||||
End Loc
|
||||
}
|
||||
|
||||
// ExecuteTextEvent runs a text event
|
||||
func ExecuteTextEvent(t *TextEvent, buf *Buffer) {
|
||||
if t.EventType == TextEventInsert {
|
||||
buf.insert(t.Start, []byte(t.Text))
|
||||
for _, d := range t.Deltas {
|
||||
buf.insert(d.Start, []byte(d.Text))
|
||||
}
|
||||
} else if t.EventType == TextEventRemove {
|
||||
t.Text = buf.remove(t.Start, t.End)
|
||||
for i, d := range t.Deltas {
|
||||
t.Deltas[i].Text = buf.remove(d.Start, d.End)
|
||||
}
|
||||
} else if t.EventType == TextEventReplace {
|
||||
for i, d := range t.Deltas {
|
||||
t.Deltas[i].Text = buf.remove(d.Start, d.End)
|
||||
buf.insert(d.Start, []byte(d.Text))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,12 +99,11 @@ func (eh *EventHandler) Insert(start Loc, text string) {
|
||||
e := &TextEvent{
|
||||
C: eh.buf.Cursor,
|
||||
EventType: TextEventInsert,
|
||||
Text: text,
|
||||
Start: start,
|
||||
Deltas: []Delta{Delta{text, start, Loc{0, 0}}},
|
||||
Time: time.Now(),
|
||||
}
|
||||
eh.Execute(e)
|
||||
e.End = start.Move(Count(text), eh.buf)
|
||||
e.Deltas[0].End = start.Move(Count(text), eh.buf)
|
||||
}
|
||||
|
||||
// Remove creates a remove text event and executes it
|
||||
@@ -97,8 +111,18 @@ func (eh *EventHandler) Remove(start, end Loc) {
|
||||
e := &TextEvent{
|
||||
C: eh.buf.Cursor,
|
||||
EventType: TextEventRemove,
|
||||
Start: start,
|
||||
End: end,
|
||||
Deltas: []Delta{Delta{"", start, end}},
|
||||
Time: time.Now(),
|
||||
}
|
||||
eh.Execute(e)
|
||||
}
|
||||
|
||||
// Multiple creates an multiple insertions executes them
|
||||
func (eh *EventHandler) MultipleReplace(deltas []Delta) {
|
||||
e := &TextEvent{
|
||||
C: eh.buf.Cursor,
|
||||
EventType: TextEventReplace,
|
||||
Deltas: deltas,
|
||||
Time: time.Now(),
|
||||
}
|
||||
eh.Execute(e)
|
||||
|
||||
18
cmd/micro/highlight/ftdetect.go
Normal file
18
cmd/micro/highlight/ftdetect.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package highlight
|
||||
|
||||
import "regexp"
|
||||
|
||||
// DetectFiletype will use the list of syntax definitions provided and the filename and first line of the file
|
||||
// to determine the filetype of the file
|
||||
// It will return the corresponding syntax definition for the filetype
|
||||
func MatchFiletype(ftdetect [2]*regexp.Regexp, filename string, firstLine []byte) bool {
|
||||
if ftdetect[0].MatchString(filename) {
|
||||
return true
|
||||
}
|
||||
|
||||
if ftdetect[1] != nil {
|
||||
return ftdetect[1].Match(firstLine)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
374
cmd/micro/highlight/highlighter.go
Normal file
374
cmd/micro/highlight/highlighter.go
Normal file
@@ -0,0 +1,374 @@
|
||||
package highlight
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// RunePos returns the rune index of a given byte index
|
||||
// This could cause problems if the byte index is between code points
|
||||
func runePos(p int, str string) int {
|
||||
if p < 0 {
|
||||
return 0
|
||||
}
|
||||
if p >= len(str) {
|
||||
return utf8.RuneCountInString(str)
|
||||
}
|
||||
return utf8.RuneCountInString(str[:p])
|
||||
}
|
||||
|
||||
func combineLineMatch(src, dst LineMatch) LineMatch {
|
||||
for k, v := range src {
|
||||
if g, ok := dst[k]; ok {
|
||||
if g == 0 {
|
||||
dst[k] = v
|
||||
}
|
||||
} else {
|
||||
dst[k] = v
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// A State represents the region at the end of a line
|
||||
type State *region
|
||||
|
||||
// LineStates is an interface for a buffer-like object which can also store the states and matches for every line
|
||||
type LineStates interface {
|
||||
Line(n int) string
|
||||
LinesNum() int
|
||||
State(lineN int) State
|
||||
SetState(lineN int, s State)
|
||||
SetMatch(lineN int, m LineMatch)
|
||||
}
|
||||
|
||||
// A Highlighter contains the information needed to highlight a string
|
||||
type Highlighter struct {
|
||||
lastRegion *region
|
||||
Def *Def
|
||||
}
|
||||
|
||||
// NewHighlighter returns a new highlighter from the given syntax definition
|
||||
func NewHighlighter(def *Def) *Highlighter {
|
||||
h := new(Highlighter)
|
||||
h.Def = def
|
||||
return h
|
||||
}
|
||||
|
||||
// LineMatch represents the syntax highlighting matches for one line. Each index where the coloring is changed is marked with that
|
||||
// color's group (represented as one byte)
|
||||
type LineMatch map[int]Group
|
||||
|
||||
func findIndex(regex *regexp.Regexp, skip *regexp.Regexp, str []rune, canMatchStart, canMatchEnd bool) []int {
|
||||
regexStr := regex.String()
|
||||
if strings.Contains(regexStr, "^") {
|
||||
if !canMatchStart {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if strings.Contains(regexStr, "$") {
|
||||
if !canMatchEnd {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var strbytes []byte
|
||||
if skip != nil {
|
||||
strbytes = skip.ReplaceAllFunc([]byte(string(str)), func(match []byte) []byte {
|
||||
res := make([]byte, utf8.RuneCount(match))
|
||||
return res
|
||||
})
|
||||
} else {
|
||||
strbytes = []byte(string(str))
|
||||
}
|
||||
|
||||
match := regex.FindIndex(strbytes)
|
||||
if match == nil {
|
||||
return nil
|
||||
}
|
||||
// return []int{match.Index, match.Index + match.Length}
|
||||
return []int{runePos(match[0], string(str)), runePos(match[1], string(str))}
|
||||
}
|
||||
|
||||
func findAllIndex(regex *regexp.Regexp, str []rune, canMatchStart, canMatchEnd bool) [][]int {
|
||||
regexStr := regex.String()
|
||||
if strings.Contains(regexStr, "^") {
|
||||
if !canMatchStart {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if strings.Contains(regexStr, "$") {
|
||||
if !canMatchEnd {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
matches := regex.FindAllIndex([]byte(string(str)), -1)
|
||||
for i, m := range matches {
|
||||
matches[i][0] = runePos(m[0], string(str))
|
||||
matches[i][1] = runePos(m[1], string(str))
|
||||
}
|
||||
return matches
|
||||
}
|
||||
|
||||
func (h *Highlighter) highlightRegion(highlights LineMatch, start int, canMatchEnd bool, lineNum int, line []rune, curRegion *region, statesOnly bool) LineMatch {
|
||||
// highlights := make(LineMatch)
|
||||
|
||||
if start == 0 {
|
||||
if !statesOnly {
|
||||
if _, ok := highlights[0]; !ok {
|
||||
highlights[0] = curRegion.group
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loc := findIndex(curRegion.end, curRegion.skip, line, start == 0, canMatchEnd)
|
||||
if loc != nil {
|
||||
if !statesOnly {
|
||||
highlights[start+loc[0]] = curRegion.limitGroup
|
||||
}
|
||||
if curRegion.parent == nil {
|
||||
if !statesOnly {
|
||||
highlights[start+loc[1]] = 0
|
||||
h.highlightRegion(highlights, start, false, lineNum, line[:loc[0]], curRegion, statesOnly)
|
||||
}
|
||||
h.highlightEmptyRegion(highlights, start+loc[1], canMatchEnd, lineNum, line[loc[1]:], statesOnly)
|
||||
return highlights
|
||||
}
|
||||
if !statesOnly {
|
||||
highlights[start+loc[1]] = curRegion.parent.group
|
||||
h.highlightRegion(highlights, start, false, lineNum, line[:loc[0]], curRegion, statesOnly)
|
||||
}
|
||||
h.highlightRegion(highlights, start+loc[1], canMatchEnd, lineNum, line[loc[1]:], curRegion.parent, statesOnly)
|
||||
return highlights
|
||||
}
|
||||
|
||||
if len(line) == 0 || statesOnly {
|
||||
if canMatchEnd {
|
||||
h.lastRegion = curRegion
|
||||
}
|
||||
|
||||
return highlights
|
||||
}
|
||||
|
||||
firstLoc := []int{len(line), 0}
|
||||
|
||||
var firstRegion *region
|
||||
for _, r := range curRegion.rules.regions {
|
||||
loc := findIndex(r.start, nil, line, start == 0, canMatchEnd)
|
||||
if loc != nil {
|
||||
if loc[0] < firstLoc[0] {
|
||||
firstLoc = loc
|
||||
firstRegion = r
|
||||
}
|
||||
}
|
||||
}
|
||||
if firstLoc[0] != len(line) {
|
||||
highlights[start+firstLoc[0]] = firstRegion.limitGroup
|
||||
h.highlightRegion(highlights, start, false, lineNum, line[:firstLoc[0]], curRegion, statesOnly)
|
||||
h.highlightRegion(highlights, start+firstLoc[1], canMatchEnd, lineNum, line[firstLoc[1]:], firstRegion, statesOnly)
|
||||
return highlights
|
||||
}
|
||||
|
||||
fullHighlights := make([]Group, len([]rune(string(line))))
|
||||
for i := 0; i < len(fullHighlights); i++ {
|
||||
fullHighlights[i] = curRegion.group
|
||||
}
|
||||
|
||||
for _, p := range curRegion.rules.patterns {
|
||||
matches := findAllIndex(p.regex, line, start == 0, canMatchEnd)
|
||||
for _, m := range matches {
|
||||
for i := m[0]; i < m[1]; i++ {
|
||||
fullHighlights[i] = p.group
|
||||
}
|
||||
}
|
||||
}
|
||||
for i, h := range fullHighlights {
|
||||
if i == 0 || h != fullHighlights[i-1] {
|
||||
// if _, ok := highlights[start+i]; !ok {
|
||||
highlights[start+i] = h
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
if canMatchEnd {
|
||||
h.lastRegion = curRegion
|
||||
}
|
||||
|
||||
return highlights
|
||||
}
|
||||
|
||||
func (h *Highlighter) highlightEmptyRegion(highlights LineMatch, start int, canMatchEnd bool, lineNum int, line []rune, statesOnly bool) LineMatch {
|
||||
if len(line) == 0 {
|
||||
if canMatchEnd {
|
||||
h.lastRegion = nil
|
||||
}
|
||||
return highlights
|
||||
}
|
||||
|
||||
firstLoc := []int{len(line), 0}
|
||||
var firstRegion *region
|
||||
for _, r := range h.Def.rules.regions {
|
||||
loc := findIndex(r.start, nil, line, start == 0, canMatchEnd)
|
||||
if loc != nil {
|
||||
if loc[0] < firstLoc[0] {
|
||||
firstLoc = loc
|
||||
firstRegion = r
|
||||
}
|
||||
}
|
||||
}
|
||||
if firstLoc[0] != len(line) {
|
||||
if !statesOnly {
|
||||
highlights[start+firstLoc[0]] = firstRegion.limitGroup
|
||||
}
|
||||
h.highlightEmptyRegion(highlights, start, false, lineNum, line[:firstLoc[0]], statesOnly)
|
||||
h.highlightRegion(highlights, start+firstLoc[1], canMatchEnd, lineNum, line[firstLoc[1]:], firstRegion, statesOnly)
|
||||
return highlights
|
||||
}
|
||||
|
||||
if statesOnly {
|
||||
if canMatchEnd {
|
||||
h.lastRegion = nil
|
||||
}
|
||||
|
||||
return highlights
|
||||
}
|
||||
|
||||
fullHighlights := make([]Group, len(line))
|
||||
for _, p := range h.Def.rules.patterns {
|
||||
matches := findAllIndex(p.regex, line, start == 0, canMatchEnd)
|
||||
for _, m := range matches {
|
||||
for i := m[0]; i < m[1]; i++ {
|
||||
fullHighlights[i] = p.group
|
||||
}
|
||||
}
|
||||
}
|
||||
for i, h := range fullHighlights {
|
||||
if i == 0 || h != fullHighlights[i-1] {
|
||||
// if _, ok := highlights[start+i]; !ok {
|
||||
highlights[start+i] = h
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
if canMatchEnd {
|
||||
h.lastRegion = nil
|
||||
}
|
||||
|
||||
return highlights
|
||||
}
|
||||
|
||||
// HighlightString syntax highlights a string
|
||||
// Use this function for simple syntax highlighting and use the other functions for
|
||||
// more advanced syntax highlighting. They are optimized for quick rehighlighting of the same
|
||||
// text with minor changes made
|
||||
func (h *Highlighter) HighlightString(input string) []LineMatch {
|
||||
lines := strings.Split(input, "\n")
|
||||
var lineMatches []LineMatch
|
||||
|
||||
for i := 0; i < len(lines); i++ {
|
||||
line := []rune(lines[i])
|
||||
highlights := make(LineMatch)
|
||||
|
||||
if i == 0 || h.lastRegion == nil {
|
||||
lineMatches = append(lineMatches, h.highlightEmptyRegion(highlights, 0, true, i, line, false))
|
||||
} else {
|
||||
lineMatches = append(lineMatches, h.highlightRegion(highlights, 0, true, i, line, h.lastRegion, false))
|
||||
}
|
||||
}
|
||||
|
||||
return lineMatches
|
||||
}
|
||||
|
||||
// HighlightStates correctly sets all states for the buffer
|
||||
func (h *Highlighter) HighlightStates(input LineStates) {
|
||||
for i := 0; i < input.LinesNum(); i++ {
|
||||
line := []rune(input.Line(i))
|
||||
// highlights := make(LineMatch)
|
||||
|
||||
if i == 0 || h.lastRegion == nil {
|
||||
h.highlightEmptyRegion(nil, 0, true, i, line, true)
|
||||
} else {
|
||||
h.highlightRegion(nil, 0, true, i, line, h.lastRegion, true)
|
||||
}
|
||||
|
||||
curState := h.lastRegion
|
||||
|
||||
input.SetState(i, curState)
|
||||
}
|
||||
}
|
||||
|
||||
// HighlightMatches sets the matches for each line in between startline and endline
|
||||
// It sets all other matches in the buffer to nil to conserve memory
|
||||
// This assumes that all the states are set correctly
|
||||
func (h *Highlighter) HighlightMatches(input LineStates, startline, endline int) {
|
||||
for i := startline; i < endline; i++ {
|
||||
if i >= input.LinesNum() {
|
||||
break
|
||||
}
|
||||
|
||||
line := []rune(input.Line(i))
|
||||
highlights := make(LineMatch)
|
||||
|
||||
var match LineMatch
|
||||
if i == 0 || input.State(i-1) == nil {
|
||||
match = h.highlightEmptyRegion(highlights, 0, true, i, line, false)
|
||||
} else {
|
||||
match = h.highlightRegion(highlights, 0, true, i, line, input.State(i-1), false)
|
||||
}
|
||||
|
||||
input.SetMatch(i, match)
|
||||
}
|
||||
}
|
||||
|
||||
// ReHighlightStates will scan down from `startline` and set the appropriate end of line state
|
||||
// for each line until it comes across the same state in two consecutive lines
|
||||
func (h *Highlighter) ReHighlightStates(input LineStates, startline int) {
|
||||
// lines := input.LineData()
|
||||
|
||||
h.lastRegion = nil
|
||||
if startline > 0 {
|
||||
h.lastRegion = input.State(startline - 1)
|
||||
}
|
||||
for i := startline; i < input.LinesNum(); i++ {
|
||||
line := []rune(input.Line(i))
|
||||
// highlights := make(LineMatch)
|
||||
|
||||
// var match LineMatch
|
||||
if i == 0 || h.lastRegion == nil {
|
||||
h.highlightEmptyRegion(nil, 0, true, i, line, true)
|
||||
} else {
|
||||
h.highlightRegion(nil, 0, true, i, line, h.lastRegion, true)
|
||||
}
|
||||
curState := h.lastRegion
|
||||
lastState := input.State(i)
|
||||
|
||||
input.SetState(i, curState)
|
||||
|
||||
if curState == lastState {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ReHighlightLine will rehighlight the state and match for a single line
|
||||
func (h *Highlighter) ReHighlightLine(input LineStates, lineN int) {
|
||||
line := []rune(input.Line(lineN))
|
||||
highlights := make(LineMatch)
|
||||
|
||||
h.lastRegion = nil
|
||||
if lineN > 0 {
|
||||
h.lastRegion = input.State(lineN - 1)
|
||||
}
|
||||
|
||||
var match LineMatch
|
||||
if lineN == 0 || h.lastRegion == nil {
|
||||
match = h.highlightEmptyRegion(highlights, 0, true, lineN, line, false)
|
||||
} else {
|
||||
match = h.highlightRegion(highlights, 0, true, lineN, line, h.lastRegion, false)
|
||||
}
|
||||
curState := h.lastRegion
|
||||
|
||||
input.SetMatch(lineN, match)
|
||||
input.SetState(lineN, curState)
|
||||
}
|
||||
314
cmd/micro/highlight/parser.go
Normal file
314
cmd/micro/highlight/parser.go
Normal file
@@ -0,0 +1,314 @@
|
||||
package highlight
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// A Group represents a syntax group
|
||||
type Group uint8
|
||||
|
||||
// Groups contains all of the groups that are defined
|
||||
// You can access them in the map via their string name
|
||||
var Groups map[string]Group
|
||||
var numGroups Group
|
||||
|
||||
// String returns the group name attached to the specific group
|
||||
func (g Group) String() string {
|
||||
for k, v := range Groups {
|
||||
if v == g {
|
||||
return k
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// A Def is a full syntax definition for a language
|
||||
// It has a filetype, information about how to detect the filetype based
|
||||
// on filename or header (the first line of the file)
|
||||
// Then it has the rules which define how to highlight the file
|
||||
type Def struct {
|
||||
*Header
|
||||
|
||||
rules *rules
|
||||
}
|
||||
|
||||
type Header struct {
|
||||
FileType string
|
||||
FtDetect [2]*regexp.Regexp
|
||||
}
|
||||
|
||||
type File struct {
|
||||
FileType string
|
||||
|
||||
yamlSrc map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// A Pattern is one simple syntax rule
|
||||
// It has a group that the rule belongs to, as well as
|
||||
// the regular expression to match the pattern
|
||||
type pattern struct {
|
||||
group Group
|
||||
regex *regexp.Regexp
|
||||
}
|
||||
|
||||
// rules defines which patterns and regions can be used to highlight
|
||||
// a filetype
|
||||
type rules struct {
|
||||
regions []*region
|
||||
patterns []*pattern
|
||||
includes []string
|
||||
}
|
||||
|
||||
// A region is a highlighted region (such as a multiline comment, or a string)
|
||||
// It belongs to a group, and has start and end regular expressions
|
||||
// A region also has rules of its own that only apply when matching inside the
|
||||
// region and also rules from the above region do not match inside this region
|
||||
// Note that a region may contain more regions
|
||||
type region struct {
|
||||
group Group
|
||||
limitGroup Group
|
||||
parent *region
|
||||
start *regexp.Regexp
|
||||
end *regexp.Regexp
|
||||
skip *regexp.Regexp
|
||||
rules *rules
|
||||
}
|
||||
|
||||
func init() {
|
||||
Groups = make(map[string]Group)
|
||||
}
|
||||
|
||||
func ParseFtDetect(file *File) (r [2]*regexp.Regexp, err error) {
|
||||
rules := file.yamlSrc
|
||||
|
||||
loaded := 0
|
||||
for k, v := range rules {
|
||||
if k == "detect" {
|
||||
ftdetect := v.(map[interface{}]interface{})
|
||||
if len(ftdetect) >= 1 {
|
||||
syntax, err := regexp.Compile(ftdetect["filename"].(string))
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
|
||||
r[0] = syntax
|
||||
}
|
||||
if len(ftdetect) >= 2 {
|
||||
header, err := regexp.Compile(ftdetect["header"].(string))
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
|
||||
r[1] = header
|
||||
}
|
||||
loaded++
|
||||
}
|
||||
|
||||
if loaded >= 2 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return r, err
|
||||
}
|
||||
|
||||
func ParseFile(input []byte) (f *File, err error) {
|
||||
// This is just so if we have an error, we can exit cleanly and return the parse error to the user
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = e.(error)
|
||||
}
|
||||
}()
|
||||
|
||||
var rules map[interface{}]interface{}
|
||||
if err = yaml.Unmarshal(input, &rules); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f = new(File)
|
||||
f.yamlSrc = rules
|
||||
|
||||
for k, v := range rules {
|
||||
if k == "filetype" {
|
||||
filetype := v.(string)
|
||||
|
||||
f.FileType = filetype
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return f, err
|
||||
}
|
||||
|
||||
// ParseDef parses an input syntax file into a highlight Def
|
||||
func ParseDef(f *File, header *Header) (s *Def, err error) {
|
||||
// This is just so if we have an error, we can exit cleanly and return the parse error to the user
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = e.(error)
|
||||
}
|
||||
}()
|
||||
|
||||
rules := f.yamlSrc
|
||||
|
||||
s = new(Def)
|
||||
s.Header = header
|
||||
|
||||
for k, v := range rules {
|
||||
if k == "rules" {
|
||||
inputRules := v.([]interface{})
|
||||
|
||||
rules, err := parseRules(inputRules, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.rules = rules
|
||||
}
|
||||
}
|
||||
|
||||
return s, err
|
||||
}
|
||||
|
||||
// ResolveIncludes will sort out the rules for including other filetypes
|
||||
// You should call this after parsing all the Defs
|
||||
func ResolveIncludes(def *Def, files []*File) {
|
||||
resolveIncludesInDef(files, def)
|
||||
}
|
||||
|
||||
func resolveIncludesInDef(files []*File, d *Def) {
|
||||
for _, lang := range d.rules.includes {
|
||||
for _, searchFile := range files {
|
||||
if lang == searchFile.FileType {
|
||||
searchDef, _ := ParseDef(searchFile, nil)
|
||||
d.rules.patterns = append(d.rules.patterns, searchDef.rules.patterns...)
|
||||
d.rules.regions = append(d.rules.regions, searchDef.rules.regions...)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, r := range d.rules.regions {
|
||||
resolveIncludesInRegion(files, r)
|
||||
r.parent = nil
|
||||
}
|
||||
}
|
||||
|
||||
func resolveIncludesInRegion(files []*File, region *region) {
|
||||
for _, lang := range region.rules.includes {
|
||||
for _, searchFile := range files {
|
||||
if lang == searchFile.FileType {
|
||||
searchDef, _ := ParseDef(searchFile, nil)
|
||||
region.rules.patterns = append(region.rules.patterns, searchDef.rules.patterns...)
|
||||
region.rules.regions = append(region.rules.regions, searchDef.rules.regions...)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, r := range region.rules.regions {
|
||||
resolveIncludesInRegion(files, r)
|
||||
r.parent = region
|
||||
}
|
||||
}
|
||||
|
||||
func parseRules(input []interface{}, curRegion *region) (*rules, error) {
|
||||
rules := new(rules)
|
||||
|
||||
for _, v := range input {
|
||||
rule := v.(map[interface{}]interface{})
|
||||
for k, val := range rule {
|
||||
group := k
|
||||
|
||||
switch object := val.(type) {
|
||||
case string:
|
||||
if k == "include" {
|
||||
rules.includes = append(rules.includes, object)
|
||||
} else {
|
||||
// Pattern
|
||||
r, err := regexp.Compile(object)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
groupStr := group.(string)
|
||||
if _, ok := Groups[groupStr]; !ok {
|
||||
numGroups++
|
||||
Groups[groupStr] = numGroups
|
||||
}
|
||||
groupNum := Groups[groupStr]
|
||||
rules.patterns = append(rules.patterns, &pattern{groupNum, r})
|
||||
}
|
||||
case map[interface{}]interface{}:
|
||||
// region
|
||||
region, err := parseRegion(group.(string), object, curRegion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rules.regions = append(rules.regions, region)
|
||||
default:
|
||||
return nil, fmt.Errorf("Bad type %T", object)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func parseRegion(group string, regionInfo map[interface{}]interface{}, prevRegion *region) (*region, error) {
|
||||
var err error
|
||||
|
||||
region := new(region)
|
||||
if _, ok := Groups[group]; !ok {
|
||||
numGroups++
|
||||
Groups[group] = numGroups
|
||||
}
|
||||
groupNum := Groups[group]
|
||||
region.group = groupNum
|
||||
region.parent = prevRegion
|
||||
|
||||
region.start, err = regexp.Compile(regionInfo["start"].(string))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
region.end, err = regexp.Compile(regionInfo["end"].(string))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// skip is optional
|
||||
if _, ok := regionInfo["skip"]; ok {
|
||||
region.skip, err = regexp.Compile(regionInfo["skip"].(string))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// limit-color is optional
|
||||
if _, ok := regionInfo["limit-group"]; ok {
|
||||
groupStr := regionInfo["limit-group"].(string)
|
||||
if _, ok := Groups[groupStr]; !ok {
|
||||
numGroups++
|
||||
Groups[groupStr] = numGroups
|
||||
}
|
||||
groupNum := Groups[groupStr]
|
||||
region.limitGroup = groupNum
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
region.limitGroup = region.group
|
||||
}
|
||||
|
||||
region.rules, err = parseRules(regionInfo["rules"].([]interface{}), region)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return region, nil
|
||||
}
|
||||
@@ -1,368 +1,28 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
import "github.com/zyedidia/micro/cmd/micro/highlight"
|
||||
|
||||
"github.com/zyedidia/tcell"
|
||||
)
|
||||
var syntaxFiles []*highlight.File
|
||||
|
||||
// FileTypeRules represents a complete set of syntax rules for a filetype
|
||||
type FileTypeRules struct {
|
||||
filetype string
|
||||
filename string
|
||||
text string
|
||||
}
|
||||
|
||||
// SyntaxRule represents a regex to highlight in a certain style
|
||||
type SyntaxRule struct {
|
||||
// What to highlight
|
||||
regex *regexp.Regexp
|
||||
// Any flags
|
||||
flags string
|
||||
// Whether this regex is a start=... end=... regex
|
||||
startend bool
|
||||
// How to highlight it
|
||||
style tcell.Style
|
||||
}
|
||||
|
||||
var syntaxKeys [][2]*regexp.Regexp
|
||||
var syntaxFiles map[[2]*regexp.Regexp]FileTypeRules
|
||||
|
||||
// LoadSyntaxFiles loads the syntax files from the default directory (configDir)
|
||||
func LoadSyntaxFiles() {
|
||||
InitColorscheme()
|
||||
syntaxFiles = make(map[[2]*regexp.Regexp]FileTypeRules)
|
||||
for _, f := range ListRuntimeFiles(RTSyntax) {
|
||||
data, err := f.Data()
|
||||
if err != nil {
|
||||
TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
|
||||
} else {
|
||||
LoadSyntaxFile(string(data), f.Name())
|
||||
LoadSyntaxFile(data, f.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// JoinRule takes a syntax rule (which can be multiple regular expressions)
|
||||
// and joins it into one regular expression by ORing everything together
|
||||
func JoinRule(rule string) string {
|
||||
split := strings.Split(rule, `" "`)
|
||||
joined := strings.Join(split, ")|(")
|
||||
joined = "(" + joined + ")"
|
||||
return joined
|
||||
}
|
||||
|
||||
// LoadSyntaxFile simply gets the filetype of a the syntax file and the source for the
|
||||
// file and creates FileTypeRules out of it. If this filetype is the one opened by the user
|
||||
// the rules will be loaded and compiled later
|
||||
// In this function we are only concerned with loading the syntax and header regexes
|
||||
func LoadSyntaxFile(text, filename string) {
|
||||
var err error
|
||||
lines := strings.Split(string(text), "\n")
|
||||
|
||||
// Regex for parsing syntax statements
|
||||
syntaxParser := regexp.MustCompile(`syntax "(.*?)"\s+"(.*)"+`)
|
||||
// Regex for parsing header statements
|
||||
headerParser := regexp.MustCompile(`header "(.*)"`)
|
||||
|
||||
// Is there a syntax definition in this file?
|
||||
hasSyntax := syntaxParser.MatchString(text)
|
||||
// Is there a header definition in this file?
|
||||
hasHeader := headerParser.MatchString(text)
|
||||
|
||||
var syntaxRegex *regexp.Regexp
|
||||
var headerRegex *regexp.Regexp
|
||||
var filetype string
|
||||
for lineNum, line := range lines {
|
||||
if (hasSyntax == (syntaxRegex != nil)) && (hasHeader == (headerRegex != nil)) {
|
||||
// We found what we we're supposed to find
|
||||
break
|
||||
}
|
||||
|
||||
if strings.TrimSpace(line) == "" ||
|
||||
strings.TrimSpace(line)[0] == '#' {
|
||||
// Ignore this line
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "syntax") {
|
||||
// Syntax statement
|
||||
syntaxMatches := syntaxParser.FindSubmatch([]byte(line))
|
||||
if len(syntaxMatches) == 3 {
|
||||
if syntaxRegex != nil {
|
||||
TermError(filename, lineNum, "Syntax statement redeclaration")
|
||||
}
|
||||
|
||||
filetype = string(syntaxMatches[1])
|
||||
extensions := JoinRule(string(syntaxMatches[2]))
|
||||
|
||||
syntaxRegex, err = regexp.Compile(extensions)
|
||||
if err != nil {
|
||||
TermError(filename, lineNum, err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
TermError(filename, lineNum, "Syntax statement is not valid: "+line)
|
||||
continue
|
||||
}
|
||||
} else if strings.HasPrefix(line, "header") {
|
||||
// Header statement
|
||||
headerMatches := headerParser.FindSubmatch([]byte(line))
|
||||
if len(headerMatches) == 2 {
|
||||
header := JoinRule(string(headerMatches[1]))
|
||||
|
||||
headerRegex, err = regexp.Compile(header)
|
||||
if err != nil {
|
||||
TermError(filename, lineNum, "Regex error: "+err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
TermError(filename, lineNum, "Header statement is not valid: "+line)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
if syntaxRegex != nil {
|
||||
// Add the current rules to the syntaxFiles variable
|
||||
regexes := [2]*regexp.Regexp{syntaxRegex, headerRegex}
|
||||
syntaxKeys = append(syntaxKeys, regexes)
|
||||
syntaxFiles[regexes] = FileTypeRules{filetype, filename, text}
|
||||
}
|
||||
}
|
||||
|
||||
// LoadRulesFromFile loads just the syntax rules from a given file
|
||||
// Only the necessary rules are loaded when the buffer is opened.
|
||||
// If we load all the rules for every filetype when micro starts, there's a bit of lag
|
||||
// A rule just explains how to color certain regular expressions
|
||||
// Example: color comment "//.*"
|
||||
// This would color all strings that match the regex "//.*" in the comment color defined
|
||||
// by the colorscheme
|
||||
func LoadRulesFromFile(text, filename string) []SyntaxRule {
|
||||
lines := strings.Split(string(text), "\n")
|
||||
|
||||
// Regex for parsing standard syntax rules
|
||||
ruleParser := regexp.MustCompile(`color (.*?)\s+(?:\((.*?)\)\s+)?"(.*)"`)
|
||||
// Regex for parsing syntax rules with start="..." end="..."
|
||||
ruleStartEndParser := regexp.MustCompile(`color (.*?)\s+(?:\((.*?)\)\s+)?start="(.*)"\s+end="(.*)"`)
|
||||
|
||||
var rules []SyntaxRule
|
||||
for lineNum, line := range lines {
|
||||
if strings.TrimSpace(line) == "" ||
|
||||
strings.TrimSpace(line)[0] == '#' ||
|
||||
strings.HasPrefix(line, "syntax") ||
|
||||
strings.HasPrefix(line, "header") {
|
||||
// Ignore this line
|
||||
continue
|
||||
}
|
||||
|
||||
// Syntax rule, but it could be standard or start-end
|
||||
if ruleParser.MatchString(line) {
|
||||
// Standard syntax rule
|
||||
// Parse the line
|
||||
submatch := ruleParser.FindSubmatch([]byte(line))
|
||||
var color string
|
||||
var regexStr string
|
||||
var flags string
|
||||
if len(submatch) == 4 {
|
||||
// If len is 4 then the user specified some additional flags to use
|
||||
color = string(submatch[1])
|
||||
flags = string(submatch[2])
|
||||
regexStr = "(?" + flags + ")" + JoinRule(string(submatch[3]))
|
||||
} else if len(submatch) == 3 {
|
||||
// If len is 3, no additional flags were given
|
||||
color = string(submatch[1])
|
||||
regexStr = JoinRule(string(submatch[2]))
|
||||
} else {
|
||||
// If len is not 3 or 4 there is a problem
|
||||
TermError(filename, lineNum, "Invalid statement: "+line)
|
||||
continue
|
||||
}
|
||||
// Compile the regex
|
||||
regex, err := regexp.Compile(regexStr)
|
||||
if err != nil {
|
||||
TermError(filename, lineNum, err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
// Get the style
|
||||
// The user could give us a "color" that is really a part of the colorscheme
|
||||
// in which case we should look that up in the colorscheme
|
||||
// They can also just give us a straight up color
|
||||
st := defStyle
|
||||
groups := strings.Split(color, ".")
|
||||
if len(groups) > 1 {
|
||||
curGroup := ""
|
||||
for i, g := range groups {
|
||||
if i != 0 {
|
||||
curGroup += "."
|
||||
}
|
||||
curGroup += g
|
||||
if style, ok := colorscheme[curGroup]; ok {
|
||||
st = style
|
||||
}
|
||||
}
|
||||
} else if style, ok := colorscheme[color]; ok {
|
||||
st = style
|
||||
} else {
|
||||
st = StringToStyle(color)
|
||||
}
|
||||
// Add the regex, flags, and style
|
||||
// False because this is not start-end
|
||||
rules = append(rules, SyntaxRule{regex, flags, false, st})
|
||||
} else if ruleStartEndParser.MatchString(line) {
|
||||
// Start-end syntax rule
|
||||
submatch := ruleStartEndParser.FindSubmatch([]byte(line))
|
||||
var color string
|
||||
var start string
|
||||
var end string
|
||||
// Use m and s flags by default
|
||||
flags := "ms"
|
||||
if len(submatch) == 5 {
|
||||
// If len is 5 the user provided some additional flags
|
||||
color = string(submatch[1])
|
||||
flags += string(submatch[2])
|
||||
start = string(submatch[3])
|
||||
end = string(submatch[4])
|
||||
} else if len(submatch) == 4 {
|
||||
// If len is 4 the user did not provide additional flags
|
||||
color = string(submatch[1])
|
||||
start = string(submatch[2])
|
||||
end = string(submatch[3])
|
||||
} else {
|
||||
// If len is not 4 or 5 there is a problem
|
||||
TermError(filename, lineNum, "Invalid statement: "+line)
|
||||
continue
|
||||
}
|
||||
|
||||
// Compile the regex
|
||||
regex, err := regexp.Compile("(?" + flags + ")" + "(" + start + ").*?(" + end + ")")
|
||||
if err != nil {
|
||||
TermError(filename, lineNum, err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
// Get the style
|
||||
// The user could give us a "color" that is really a part of the colorscheme
|
||||
// in which case we should look that up in the colorscheme
|
||||
// They can also just give us a straight up color
|
||||
st := defStyle
|
||||
if _, ok := colorscheme[color]; ok {
|
||||
st = colorscheme[color]
|
||||
} else {
|
||||
st = StringToStyle(color)
|
||||
}
|
||||
// Add the regex, flags, and style
|
||||
// True because this is start-end
|
||||
rules = append(rules, SyntaxRule{regex, flags, true, st})
|
||||
}
|
||||
}
|
||||
return rules
|
||||
}
|
||||
|
||||
// FindFileType finds the filetype for the given buffer
|
||||
func FindFileType(buf *Buffer) string {
|
||||
for _, r := range syntaxKeys {
|
||||
if r[1] != nil && r[1].MatchString(buf.Line(0)) {
|
||||
// The header statement matches the first line
|
||||
return syntaxFiles[r].filetype
|
||||
}
|
||||
}
|
||||
for _, r := range syntaxKeys {
|
||||
if r[0] != nil && r[0].MatchString(buf.Path) {
|
||||
// The syntax statement matches the extension
|
||||
return syntaxFiles[r].filetype
|
||||
}
|
||||
}
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
// GetRules finds the syntax rules that should be used for the buffer
|
||||
// and returns them. It also returns the filetype of the file
|
||||
func GetRules(buf *Buffer) []SyntaxRule {
|
||||
for _, r := range syntaxKeys {
|
||||
if syntaxFiles[r].filetype == buf.FileType() {
|
||||
return LoadRulesFromFile(syntaxFiles[r].text, syntaxFiles[r].filename)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SyntaxMatches is an alias to a map from character numbers to styles,
|
||||
// so map[3] represents the style of the third character
|
||||
type SyntaxMatches [][]tcell.Style
|
||||
|
||||
// Match takes a buffer and returns the syntax matches: a 2d array specifying how it should be syntax highlighted
|
||||
// We match the rules from up `synLinesUp` lines and down `synLinesDown` lines
|
||||
func Match(v *View) SyntaxMatches {
|
||||
buf := v.Buf
|
||||
rules := v.Buf.rules
|
||||
|
||||
viewStart := v.Topline
|
||||
viewEnd := v.Topline + v.Height
|
||||
if viewEnd > buf.NumLines {
|
||||
viewEnd = buf.NumLines
|
||||
}
|
||||
|
||||
lines := buf.Lines(viewStart, viewEnd)
|
||||
matches := make(SyntaxMatches, len(lines))
|
||||
|
||||
for i, line := range lines {
|
||||
matches[i] = make([]tcell.Style, len(line)+1)
|
||||
for j := range matches[i] {
|
||||
matches[i][j] = defStyle
|
||||
}
|
||||
}
|
||||
|
||||
// We don't actually check the entire buffer, just from synLinesUp to synLinesDown
|
||||
totalStart := v.Topline - synLinesUp
|
||||
totalEnd := v.Topline + v.Height + synLinesDown
|
||||
if totalStart < 0 {
|
||||
totalStart = 0
|
||||
}
|
||||
if totalEnd > buf.NumLines {
|
||||
totalEnd = buf.NumLines
|
||||
}
|
||||
|
||||
str := strings.Join(buf.Lines(totalStart, totalEnd), "\n")
|
||||
startNum := ToCharPos(Loc{0, totalStart}, v.Buf)
|
||||
|
||||
for _, rule := range rules {
|
||||
if rule.startend {
|
||||
if indicies := rule.regex.FindAllStringIndex(str, -1); indicies != nil {
|
||||
for _, value := range indicies {
|
||||
value[0] = runePos(value[0], str) + startNum
|
||||
value[1] = runePos(value[1], str) + startNum
|
||||
startLoc := FromCharPos(value[0], buf)
|
||||
endLoc := FromCharPos(value[1], buf)
|
||||
for curLoc := startLoc; curLoc.LessThan(endLoc); curLoc = curLoc.Move(1, buf) {
|
||||
if curLoc.Y < v.Topline {
|
||||
continue
|
||||
}
|
||||
colNum, lineNum := curLoc.X, curLoc.Y
|
||||
if lineNum == -1 || colNum == -1 {
|
||||
continue
|
||||
}
|
||||
lineNum -= viewStart
|
||||
if lineNum >= 0 && lineNum < v.Height {
|
||||
matches[lineNum][colNum] = rule.style
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for lineN, line := range lines {
|
||||
if indicies := rule.regex.FindAllStringIndex(line, -1); indicies != nil {
|
||||
for _, value := range indicies {
|
||||
start := runePos(value[0], line)
|
||||
end := runePos(value[1], line)
|
||||
for i := start; i < end; i++ {
|
||||
matches[lineN][i] = rule.style
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matches
|
||||
func LoadSyntaxFile(text []byte, filename string) {
|
||||
f, err := highlight.ParseFile(text)
|
||||
|
||||
if err != nil {
|
||||
TermMessage("Syntax file error: " + filename + ": " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
syntaxFiles = append(syntaxFiles, f)
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/zyedidia/micro/cmd/micro/highlight"
|
||||
)
|
||||
|
||||
func runeToByteIndex(n int, txt []byte) int {
|
||||
@@ -28,30 +29,74 @@ func runeToByteIndex(n int, txt []byte) int {
|
||||
return count
|
||||
}
|
||||
|
||||
type Line struct {
|
||||
data []byte
|
||||
|
||||
state highlight.State
|
||||
match highlight.LineMatch
|
||||
rehighlight bool
|
||||
}
|
||||
|
||||
// A LineArray simply stores and array of lines and makes it easy to insert
|
||||
// and delete in it
|
||||
type LineArray struct {
|
||||
lines [][]byte
|
||||
lines []Line
|
||||
}
|
||||
|
||||
func Append(slice []Line, data ...Line) []Line {
|
||||
l := len(slice)
|
||||
if l+len(data) > cap(slice) { // reallocate
|
||||
// Allocate double what's needed, for future growth.
|
||||
newSlice := make([]Line, (l+len(data))+10000)
|
||||
// The copy function is predeclared and works for any slice type.
|
||||
copy(newSlice, slice)
|
||||
slice = newSlice
|
||||
}
|
||||
slice = slice[0 : l+len(data)]
|
||||
for i, c := range data {
|
||||
slice[l+i] = c
|
||||
}
|
||||
return slice
|
||||
}
|
||||
|
||||
// NewLineArray returns a new line array from an array of bytes
|
||||
func NewLineArray(reader io.Reader) *LineArray {
|
||||
func NewLineArray(size int64, reader io.Reader) *LineArray {
|
||||
la := new(LineArray)
|
||||
br := bufio.NewReader(reader)
|
||||
|
||||
i := 0
|
||||
la.lines = make([]Line, 0, 1000)
|
||||
|
||||
br := bufio.NewReader(reader)
|
||||
var loaded int
|
||||
|
||||
n := 0
|
||||
for {
|
||||
data, err := br.ReadBytes('\n')
|
||||
|
||||
if n >= 1000 && loaded >= 0 {
|
||||
totalLinesNum := int(float64(size) * (float64(n) / float64(loaded)))
|
||||
newSlice := make([]Line, len(la.lines), totalLinesNum+10000)
|
||||
// The copy function is predeclared and works for any slice type.
|
||||
copy(newSlice, la.lines)
|
||||
la.lines = newSlice
|
||||
loaded = -1
|
||||
}
|
||||
|
||||
if loaded >= 0 {
|
||||
loaded += len(data)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
la.lines = append(la.lines, data[:len(data)])
|
||||
la.lines = Append(la.lines, Line{data[:len(data)], nil, nil, false})
|
||||
// la.lines = Append(la.lines, Line{data[:len(data)]})
|
||||
}
|
||||
// Last line was read
|
||||
break
|
||||
} else {
|
||||
la.lines = append(la.lines, data[:len(data)-1])
|
||||
// la.lines = Append(la.lines, Line{data[:len(data)-1]})
|
||||
la.lines = Append(la.lines, Line{data[:len(data)-1], nil, nil, false})
|
||||
}
|
||||
i++
|
||||
n++
|
||||
}
|
||||
|
||||
return la
|
||||
@@ -59,19 +104,26 @@ func NewLineArray(reader io.Reader) *LineArray {
|
||||
|
||||
// Returns the String representation of the LineArray
|
||||
func (la *LineArray) String() string {
|
||||
return string(bytes.Join(la.lines, []byte("\n")))
|
||||
str := ""
|
||||
for i, l := range la.lines {
|
||||
str += string(l.data)
|
||||
if i != len(la.lines)-1 {
|
||||
str += "\n"
|
||||
}
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// NewlineBelow adds a newline below the given line number
|
||||
func (la *LineArray) NewlineBelow(y int) {
|
||||
la.lines = append(la.lines, []byte(" "))
|
||||
la.lines = append(la.lines, Line{[]byte(" "), nil, nil, false})
|
||||
copy(la.lines[y+2:], la.lines[y+1:])
|
||||
la.lines[y+1] = []byte("")
|
||||
la.lines[y+1] = Line{[]byte(""), la.lines[y].state, nil, false}
|
||||
}
|
||||
|
||||
// inserts a byte array at a given location
|
||||
func (la *LineArray) insert(pos Loc, value []byte) {
|
||||
x, y := runeToByteIndex(pos.X, la.lines[pos.Y]), pos.Y
|
||||
x, y := runeToByteIndex(pos.X, la.lines[pos.Y].data), pos.Y
|
||||
// x, y := pos.x, pos.y
|
||||
for i := 0; i < len(value); i++ {
|
||||
if value[i] == '\n' {
|
||||
@@ -87,31 +139,36 @@ func (la *LineArray) insert(pos Loc, value []byte) {
|
||||
|
||||
// inserts a byte at a given location
|
||||
func (la *LineArray) insertByte(pos Loc, value byte) {
|
||||
la.lines[pos.Y] = append(la.lines[pos.Y], 0)
|
||||
copy(la.lines[pos.Y][pos.X+1:], la.lines[pos.Y][pos.X:])
|
||||
la.lines[pos.Y][pos.X] = value
|
||||
la.lines[pos.Y].data = append(la.lines[pos.Y].data, 0)
|
||||
copy(la.lines[pos.Y].data[pos.X+1:], la.lines[pos.Y].data[pos.X:])
|
||||
la.lines[pos.Y].data[pos.X] = value
|
||||
}
|
||||
|
||||
// JoinLines joins the two lines a and b
|
||||
func (la *LineArray) JoinLines(a, b int) {
|
||||
la.insert(Loc{len(la.lines[a]), a}, la.lines[b])
|
||||
la.insert(Loc{len(la.lines[a].data), a}, la.lines[b].data)
|
||||
la.DeleteLine(b)
|
||||
}
|
||||
|
||||
// Split splits a line at a given position
|
||||
func (la *LineArray) Split(pos Loc) {
|
||||
la.NewlineBelow(pos.Y)
|
||||
la.insert(Loc{0, pos.Y + 1}, la.lines[pos.Y][pos.X:])
|
||||
la.insert(Loc{0, pos.Y + 1}, la.lines[pos.Y].data[pos.X:])
|
||||
la.lines[pos.Y+1].state = la.lines[pos.Y].state
|
||||
la.lines[pos.Y].state = nil
|
||||
la.lines[pos.Y].match = nil
|
||||
la.lines[pos.Y+1].match = nil
|
||||
la.lines[pos.Y].rehighlight = true
|
||||
la.DeleteToEnd(Loc{pos.X, pos.Y})
|
||||
}
|
||||
|
||||
// removes from start to end
|
||||
func (la *LineArray) remove(start, end Loc) string {
|
||||
sub := la.Substr(start, end)
|
||||
startX := runeToByteIndex(start.X, la.lines[start.Y])
|
||||
endX := runeToByteIndex(end.X, la.lines[end.Y])
|
||||
startX := runeToByteIndex(start.X, la.lines[start.Y].data)
|
||||
endX := runeToByteIndex(end.X, la.lines[end.Y].data)
|
||||
if start.Y == end.Y {
|
||||
la.lines[start.Y] = append(la.lines[start.Y][:startX], la.lines[start.Y][endX:]...)
|
||||
la.lines[start.Y].data = append(la.lines[start.Y].data[:startX], la.lines[start.Y].data[endX:]...)
|
||||
} else {
|
||||
for i := start.Y + 1; i <= end.Y-1; i++ {
|
||||
la.DeleteLine(start.Y + 1)
|
||||
@@ -125,12 +182,12 @@ func (la *LineArray) remove(start, end Loc) string {
|
||||
|
||||
// DeleteToEnd deletes from the end of a line to the position
|
||||
func (la *LineArray) DeleteToEnd(pos Loc) {
|
||||
la.lines[pos.Y] = la.lines[pos.Y][:pos.X]
|
||||
la.lines[pos.Y].data = la.lines[pos.Y].data[:pos.X]
|
||||
}
|
||||
|
||||
// DeleteFromStart deletes from the start of a line to the position
|
||||
func (la *LineArray) DeleteFromStart(pos Loc) {
|
||||
la.lines[pos.Y] = la.lines[pos.Y][pos.X+1:]
|
||||
la.lines[pos.Y].data = la.lines[pos.Y].data[pos.X+1:]
|
||||
}
|
||||
|
||||
// DeleteLine deletes the line number
|
||||
@@ -140,21 +197,37 @@ func (la *LineArray) DeleteLine(y int) {
|
||||
|
||||
// DeleteByte deletes the byte at a position
|
||||
func (la *LineArray) DeleteByte(pos Loc) {
|
||||
la.lines[pos.Y] = la.lines[pos.Y][:pos.X+copy(la.lines[pos.Y][pos.X:], la.lines[pos.Y][pos.X+1:])]
|
||||
la.lines[pos.Y].data = la.lines[pos.Y].data[:pos.X+copy(la.lines[pos.Y].data[pos.X:], la.lines[pos.Y].data[pos.X+1:])]
|
||||
}
|
||||
|
||||
// Substr returns the string representation between two locations
|
||||
func (la *LineArray) Substr(start, end Loc) string {
|
||||
startX := runeToByteIndex(start.X, la.lines[start.Y])
|
||||
endX := runeToByteIndex(end.X, la.lines[end.Y])
|
||||
startX := runeToByteIndex(start.X, la.lines[start.Y].data)
|
||||
endX := runeToByteIndex(end.X, la.lines[end.Y].data)
|
||||
if start.Y == end.Y {
|
||||
return string(la.lines[start.Y][startX:endX])
|
||||
return string(la.lines[start.Y].data[startX:endX])
|
||||
}
|
||||
var str string
|
||||
str += string(la.lines[start.Y][startX:]) + "\n"
|
||||
str += string(la.lines[start.Y].data[startX:]) + "\n"
|
||||
for i := start.Y + 1; i <= end.Y-1; i++ {
|
||||
str += string(la.lines[i]) + "\n"
|
||||
str += string(la.lines[i].data) + "\n"
|
||||
}
|
||||
str += string(la.lines[end.Y][:endX])
|
||||
str += string(la.lines[end.Y].data[:endX])
|
||||
return str
|
||||
}
|
||||
|
||||
func (la *LineArray) State(lineN int) highlight.State {
|
||||
return la.lines[lineN].state
|
||||
}
|
||||
|
||||
func (la *LineArray) SetState(lineN int, s highlight.State) {
|
||||
la.lines[lineN].state = s
|
||||
}
|
||||
|
||||
func (la *LineArray) SetMatch(lineN int, m highlight.LineMatch) {
|
||||
la.lines[lineN].match = m
|
||||
}
|
||||
|
||||
func (la *LineArray) Match(lineN int) highlight.LineMatch {
|
||||
return la.lines[lineN].match
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/zyedidia/clipboard"
|
||||
"github.com/zyedidia/tcell"
|
||||
@@ -79,7 +78,7 @@ func (m *Messenger) AddLog(msg string) {
|
||||
|
||||
func (m *Messenger) getBuffer() *Buffer {
|
||||
if m.log == nil {
|
||||
m.log = NewBuffer(strings.NewReader(""), "")
|
||||
m.log = NewBufferFromString("", "")
|
||||
m.log.name = "Log"
|
||||
}
|
||||
return m.log
|
||||
@@ -162,17 +161,19 @@ func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
|
||||
case *tcell.EventKey:
|
||||
switch e.Key() {
|
||||
case tcell.KeyRune:
|
||||
if e.Rune() == 'y' {
|
||||
if e.Rune() == 'y' || e.Rune() == 'Y' {
|
||||
m.AddLog("\t--> y")
|
||||
m.hasPrompt = false
|
||||
return true, false
|
||||
} else if e.Rune() == 'n' {
|
||||
} else if e.Rune() == 'n' || e.Rune() == 'N' {
|
||||
m.AddLog("\t--> n")
|
||||
m.hasPrompt = false
|
||||
return false, false
|
||||
}
|
||||
case tcell.KeyCtrlC, tcell.KeyCtrlQ, tcell.KeyEscape:
|
||||
m.AddLog("\t--> (cancel)")
|
||||
m.Clear()
|
||||
m.Reset()
|
||||
m.hasPrompt = false
|
||||
return false, true
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"layeh.com/gopher-luar"
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/yuin/gopher-lua"
|
||||
"github.com/zyedidia/clipboard"
|
||||
"github.com/zyedidia/tcell"
|
||||
"github.com/zyedidia/tcell/encoding"
|
||||
"layeh.com/gopher-luar"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -84,13 +84,14 @@ func LoadInput() []*Buffer {
|
||||
var filename string
|
||||
var input []byte
|
||||
var err error
|
||||
var buffers []*Buffer
|
||||
args := flag.Args()
|
||||
buffers := make([]*Buffer, 0, len(args))
|
||||
|
||||
if len(flag.Args()) > 0 {
|
||||
if len(args) > 0 {
|
||||
// Option 1
|
||||
// We go through each file and load it
|
||||
for i := 0; i < len(flag.Args()); i++ {
|
||||
filename = flag.Args()[i]
|
||||
for i := 0; i < len(args); i++ {
|
||||
filename = args[i]
|
||||
|
||||
// Check that the file exists
|
||||
var input *os.File
|
||||
@@ -110,9 +111,9 @@ func LoadInput() []*Buffer {
|
||||
}
|
||||
// If the file didn't exist, input will be empty, and we'll open an empty buffer
|
||||
if input != nil {
|
||||
buffers = append(buffers, NewBuffer(input, filename))
|
||||
buffers = append(buffers, NewBuffer(input, FSize(input), filename))
|
||||
} else {
|
||||
buffers = append(buffers, NewBuffer(strings.NewReader(""), filename))
|
||||
buffers = append(buffers, NewBufferFromString("", filename))
|
||||
}
|
||||
}
|
||||
} else if !isatty.IsTerminal(os.Stdin.Fd()) {
|
||||
@@ -124,10 +125,10 @@ func LoadInput() []*Buffer {
|
||||
TermMessage("Error reading from stdin: ", err)
|
||||
input = []byte{}
|
||||
}
|
||||
buffers = append(buffers, NewBuffer(strings.NewReader(string(input)), filename))
|
||||
buffers = append(buffers, NewBufferFromString(string(input), filename))
|
||||
} else {
|
||||
// Option 3, just open an empty buffer
|
||||
buffers = append(buffers, NewBuffer(strings.NewReader(string(input)), filename))
|
||||
buffers = append(buffers, NewBufferFromString(string(input), filename))
|
||||
}
|
||||
|
||||
return buffers
|
||||
@@ -201,6 +202,14 @@ func InitScreen() {
|
||||
// RedrawAll redraws everything -- all the views and the messenger
|
||||
func RedrawAll() {
|
||||
messenger.Clear()
|
||||
|
||||
w, h := screen.Size()
|
||||
for x := 0; x < w; x++ {
|
||||
for y := 0; y < h; y++ {
|
||||
screen.SetContent(x, y, ' ', nil, defStyle)
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range tabs[curTab].views {
|
||||
v.Display()
|
||||
}
|
||||
@@ -222,14 +231,11 @@ func LoadAll() {
|
||||
InitCommands()
|
||||
InitBindings()
|
||||
|
||||
LoadSyntaxFiles()
|
||||
InitColorscheme()
|
||||
|
||||
for _, tab := range tabs {
|
||||
for _, v := range tab.views {
|
||||
v.Buf.UpdateRules()
|
||||
if v.Buf.Settings["syntax"].(bool) {
|
||||
v.matches = Match(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,6 +314,7 @@ func main() {
|
||||
screen.Fini()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for _, buf := range buffers {
|
||||
// For each buffer we create a new tab and place the view in that tab
|
||||
tab := NewTabFromView(NewView(buf))
|
||||
@@ -371,6 +378,7 @@ func main() {
|
||||
L.SetGlobal("ListRuntimeFiles", luar.New(L, PluginListRuntimeFiles))
|
||||
L.SetGlobal("AddRuntimeFile", luar.New(L, PluginAddRuntimeFile))
|
||||
L.SetGlobal("AddRuntimeFilesFromDirectory", luar.New(L, PluginAddRuntimeFilesFromDirectory))
|
||||
L.SetGlobal("AddRuntimeFileFromMemory", luar.New(L, PluginAddRuntimeFileFromMemory))
|
||||
|
||||
jobs = make(chan JobFunction, 100)
|
||||
events = make(chan tcell.Event, 100)
|
||||
@@ -378,13 +386,8 @@ func main() {
|
||||
|
||||
LoadPlugins()
|
||||
|
||||
// Load the syntax files, including the colorscheme
|
||||
LoadSyntaxFiles()
|
||||
|
||||
for _, t := range tabs {
|
||||
for _, v := range t.views {
|
||||
v.Buf.FindFileType()
|
||||
v.Buf.UpdateRules()
|
||||
for pl := range loadedPlugins {
|
||||
_, err := Call(pl+".onViewOpen", v)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
|
||||
@@ -392,12 +395,11 @@ func main() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if v.Buf.Settings["syntax"].(bool) {
|
||||
v.matches = Match(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InitColorscheme()
|
||||
|
||||
// Here is the event loop which runs in a separate thread
|
||||
go func() {
|
||||
for {
|
||||
@@ -433,26 +435,32 @@ func main() {
|
||||
|
||||
for event != nil {
|
||||
switch e := event.(type) {
|
||||
case *tcell.EventResize:
|
||||
for _, t := range tabs {
|
||||
t.Resize()
|
||||
}
|
||||
case *tcell.EventMouse:
|
||||
if e.Buttons() == tcell.Button1 {
|
||||
// If the user left clicked we check a couple things
|
||||
_, h := screen.Size()
|
||||
x, y := e.Position()
|
||||
if y == h-1 && messenger.message != "" && globalSettings["infobar"].(bool) {
|
||||
// If the user clicked in the bottom bar, and there is a message down there
|
||||
// we copy it to the clipboard.
|
||||
// Often error messages are displayed down there so it can be useful to easily
|
||||
// copy the message
|
||||
clipboard.WriteAll(messenger.message, "primary")
|
||||
break
|
||||
}
|
||||
if !searching {
|
||||
if e.Buttons() == tcell.Button1 {
|
||||
// If the user left clicked we check a couple things
|
||||
_, h := screen.Size()
|
||||
x, y := e.Position()
|
||||
if y == h-1 && messenger.message != "" && globalSettings["infobar"].(bool) {
|
||||
// If the user clicked in the bottom bar, and there is a message down there
|
||||
// we copy it to the clipboard.
|
||||
// Often error messages are displayed down there so it can be useful to easily
|
||||
// copy the message
|
||||
clipboard.WriteAll(messenger.message, "primary")
|
||||
break
|
||||
}
|
||||
|
||||
if CurView().mouseReleased {
|
||||
// We loop through each view in the current tab and make sure the current view
|
||||
// is the one being clicked in
|
||||
for _, v := range tabs[curTab].views {
|
||||
if x >= v.x && x < v.x+v.Width && y >= v.y && y < v.y+v.Height {
|
||||
tabs[curTab].CurView = v.Num
|
||||
if CurView().mouseReleased {
|
||||
// We loop through each view in the current tab and make sure the current view
|
||||
// is the one being clicked in
|
||||
for _, v := range tabs[curTab].views {
|
||||
if x >= v.x && x < v.x+v.Width && y >= v.y && y < v.y+v.Height {
|
||||
tabs[curTab].CurView = v.Num
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -480,7 +488,6 @@ func main() {
|
||||
default:
|
||||
event = nil
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"layeh.com/gopher-luar"
|
||||
"github.com/yuin/gopher-lua"
|
||||
"layeh.com/gopher-luar"
|
||||
)
|
||||
|
||||
var loadedPlugins map[string]string
|
||||
|
||||
@@ -37,6 +37,19 @@ type namedFile struct {
|
||||
name string
|
||||
}
|
||||
|
||||
// a file with the data stored in memory
|
||||
type memoryFile struct {
|
||||
name string
|
||||
data []byte
|
||||
}
|
||||
|
||||
func (mf memoryFile) Name() string {
|
||||
return mf.name
|
||||
}
|
||||
func (mf memoryFile) Data() ([]byte, error) {
|
||||
return mf.data, nil
|
||||
}
|
||||
|
||||
func (rf realFile) Name() string {
|
||||
fn := filepath.Base(string(rf))
|
||||
return fn[:len(fn)-len(filepath.Ext(fn))]
|
||||
@@ -120,7 +133,7 @@ func InitRuntimeFiles() {
|
||||
}
|
||||
|
||||
add(RTColorscheme, "colorschemes", "*.micro")
|
||||
add(RTSyntax, "syntax", "*.micro")
|
||||
add(RTSyntax, "syntax", "*.yaml")
|
||||
add(RTHelp, "help", "*.md")
|
||||
|
||||
// Search configDir for plugin-scripts
|
||||
@@ -187,3 +200,8 @@ func PluginAddRuntimeFilesFromDirectory(plugin, filetype, directory, pattern str
|
||||
AddRuntimeFilesFromAssets(filetype, fullpath, pattern)
|
||||
}
|
||||
}
|
||||
|
||||
// PluginAddRuntimeFileFromMemory adds a file to the runtime files for a plugin from a given string
|
||||
func PluginAddRuntimeFileFromMemory(plugin, filetype, filename, data string) {
|
||||
AddRuntimeFile(filetype, memoryFile{filename, []byte(data)})
|
||||
}
|
||||
|
||||
3687
cmd/micro/runtime.go
3687
cmd/micro/runtime.go
File diff suppressed because one or more lines are too long
@@ -86,6 +86,8 @@ func HandleSearchEvent(event tcell.Event, v *View) {
|
||||
|
||||
Search(messenger.response, v, true)
|
||||
|
||||
v.Relocate()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -144,8 +146,5 @@ func Search(searchStr string, v *View, down bool) {
|
||||
v.Cursor.SetSelectionStart(FromCharPos(charPos+runePos(match[0], str), v.Buf))
|
||||
v.Cursor.SetSelectionEnd(FromCharPos(charPos+runePos(match[1], str), v.Buf))
|
||||
v.Cursor.Loc = v.Cursor.CurSelection[1]
|
||||
if v.Relocate() {
|
||||
v.matches = Match(v)
|
||||
}
|
||||
lastSearch = searchStr
|
||||
}
|
||||
|
||||
@@ -196,8 +196,10 @@ func DefaultGlobalSettings() map[string]interface{} {
|
||||
"splitBottom": true,
|
||||
"statusline": true,
|
||||
"syntax": true,
|
||||
"tabmovement": false,
|
||||
"tabsize": float64(4),
|
||||
"tabstospaces": false,
|
||||
"termtitle": false,
|
||||
"pluginchannels": []string{
|
||||
"https://raw.githubusercontent.com/micro-editor/plugin-channel/master/channel.json",
|
||||
},
|
||||
@@ -230,6 +232,7 @@ func DefaultLocalSettings() map[string]interface{} {
|
||||
"splitBottom": true,
|
||||
"statusline": true,
|
||||
"syntax": true,
|
||||
"tabmovement": false,
|
||||
"tabsize": float64(4),
|
||||
"tabstospaces": false,
|
||||
"useprimary": true,
|
||||
@@ -277,13 +280,11 @@ func SetOption(option, value string) error {
|
||||
globalSettings[option] = nativeValue
|
||||
|
||||
if option == "colorscheme" {
|
||||
LoadSyntaxFiles()
|
||||
// LoadSyntaxFiles()
|
||||
InitColorscheme()
|
||||
for _, tab := range tabs {
|
||||
for _, view := range tab.views {
|
||||
view.Buf.UpdateRules()
|
||||
if view.Buf.Settings["syntax"].(bool) {
|
||||
view.matches = Match(view)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -341,16 +342,19 @@ func SetLocalOption(option, value string, view *View) error {
|
||||
|
||||
if option == "statusline" {
|
||||
view.ToggleStatusLine()
|
||||
if buf.Settings["syntax"].(bool) {
|
||||
view.matches = Match(view)
|
||||
}
|
||||
}
|
||||
|
||||
if option == "filetype" {
|
||||
LoadSyntaxFiles()
|
||||
// LoadSyntaxFiles()
|
||||
InitColorscheme()
|
||||
buf.UpdateRules()
|
||||
if buf.Settings["syntax"].(bool) {
|
||||
view.matches = Match(view)
|
||||
}
|
||||
|
||||
if option == "syntax" {
|
||||
if !nativeValue.(bool) {
|
||||
buf.ClearMatches()
|
||||
} else {
|
||||
buf.highlighter.HighlightStates(buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
// SpltType specifies whether a split is horizontal or vertical
|
||||
// SplitType specifies whether a split is horizontal or vertical
|
||||
type SplitType bool
|
||||
|
||||
const (
|
||||
@@ -255,7 +255,6 @@ func (s *SplitTree) ResizeSplits() {
|
||||
}
|
||||
|
||||
n.view.ToggleTabbar()
|
||||
n.view.matches = Match(n.view)
|
||||
} else if n, ok := node.(*SplitTree); ok {
|
||||
if s.kind == VerticalSplit {
|
||||
if !n.lockWidth {
|
||||
|
||||
108
cmd/micro/tab.go
108
cmd/micro/tab.go
@@ -6,6 +6,8 @@ import (
|
||||
"github.com/zyedidia/tcell"
|
||||
)
|
||||
|
||||
var tabBarOffset int
|
||||
|
||||
type Tab struct {
|
||||
// This contains all the views in this tab
|
||||
// There is generally only one view per tab, but you can have
|
||||
@@ -87,13 +89,17 @@ func TabbarString() (string, map[int]int) {
|
||||
} else {
|
||||
str += " "
|
||||
}
|
||||
str += t.views[t.CurView].Buf.GetName()
|
||||
buf := t.views[t.CurView].Buf
|
||||
str += buf.GetName()
|
||||
if buf.IsModified {
|
||||
str += " +"
|
||||
}
|
||||
if i == curTab {
|
||||
str += "]"
|
||||
} else {
|
||||
str += " "
|
||||
}
|
||||
indicies[len(str)-1] = i + 1
|
||||
indicies[Count(str)-1] = i + 1
|
||||
str += " "
|
||||
}
|
||||
return str, indicies
|
||||
@@ -118,7 +124,7 @@ func TabbarHandleMouseEvent(event tcell.Event) bool {
|
||||
return false
|
||||
}
|
||||
str, indicies := TabbarString()
|
||||
if x >= len(str) {
|
||||
if x+tabBarOffset >= len(str) {
|
||||
return false
|
||||
}
|
||||
var tabnum int
|
||||
@@ -128,7 +134,7 @@ func TabbarHandleMouseEvent(event tcell.Event) bool {
|
||||
}
|
||||
sort.Ints(keys)
|
||||
for _, k := range keys {
|
||||
if x <= k {
|
||||
if x+tabBarOffset <= k {
|
||||
tabnum = indicies[k] - 1
|
||||
break
|
||||
}
|
||||
@@ -147,7 +153,7 @@ func DisplayTabs() {
|
||||
return
|
||||
}
|
||||
|
||||
str, _ := TabbarString()
|
||||
str, indicies := TabbarString()
|
||||
|
||||
tabBarStyle := defStyle.Reverse(true)
|
||||
if style, ok := colorscheme["tabbar"]; ok {
|
||||
@@ -157,6 +163,98 @@ func DisplayTabs() {
|
||||
// Maybe there is a unicode filename?
|
||||
fileRunes := []rune(str)
|
||||
w, _ := screen.Size()
|
||||
tooWide := (w < len(fileRunes))
|
||||
|
||||
// if the entire tab-bar is longer than the screen is wide,
|
||||
// then it should be truncated appropriately to keep the
|
||||
// active tab visible on the UI.
|
||||
if tooWide == true {
|
||||
// first we have to work out where the selected tab is
|
||||
// out of the total length of the tab bar. this is done
|
||||
// by extracting the hit-areas from the indicies map
|
||||
// that was constructed by `TabbarString()`
|
||||
var keys []int
|
||||
for offset := range indicies {
|
||||
keys = append(keys, offset)
|
||||
}
|
||||
// sort them to be in ascending order so that values will
|
||||
// correctly reflect the displayed ordering of the tabs
|
||||
sort.Ints(keys)
|
||||
// record the offset of each tab and the previous tab so
|
||||
// we can find the position of the tab's hit-box.
|
||||
previousTabOffset := 0
|
||||
currentTabOffset := 0
|
||||
for _, k := range keys {
|
||||
tabIndex := indicies[k] - 1
|
||||
if tabIndex == curTab {
|
||||
currentTabOffset = k
|
||||
break
|
||||
}
|
||||
// this is +2 because there are two padding spaces that aren't accounted
|
||||
// for in the display. please note that this is for cosmetic purposes only.
|
||||
previousTabOffset = k + 2
|
||||
}
|
||||
// get the width of the hitbox of the active tab, from there calculate the offsets
|
||||
// to the left and right of it to approximately center it on the tab bar display.
|
||||
centeringOffset := (w - (currentTabOffset - previousTabOffset))
|
||||
leftBuffer := previousTabOffset - (centeringOffset / 2)
|
||||
rightBuffer := currentTabOffset + (centeringOffset / 2)
|
||||
|
||||
// check to make sure we haven't overshot the bounds of the string,
|
||||
// if we have, then take that remainder and put it on the left side
|
||||
overshotRight := rightBuffer - len(fileRunes)
|
||||
if overshotRight > 0 {
|
||||
leftBuffer = leftBuffer + overshotRight
|
||||
}
|
||||
|
||||
overshotLeft := leftBuffer - 0
|
||||
if overshotLeft < 0 {
|
||||
leftBuffer = 0
|
||||
rightBuffer = leftBuffer + (w - 1)
|
||||
} else {
|
||||
rightBuffer = leftBuffer + (w - 2)
|
||||
}
|
||||
|
||||
if rightBuffer > len(fileRunes)-1 {
|
||||
rightBuffer = len(fileRunes) - 1
|
||||
}
|
||||
|
||||
// construct a new buffer of text to put the
|
||||
// newly formatted tab bar text into.
|
||||
var displayText []rune
|
||||
|
||||
// if the left-side of the tab bar isn't at the start
|
||||
// of the constructed tab bar text, then show that are
|
||||
// more tabs to the left by displaying a "+"
|
||||
if leftBuffer != 0 {
|
||||
displayText = append(displayText, '+')
|
||||
}
|
||||
// copy the runes in from the original tab bar text string
|
||||
// into the new display buffer
|
||||
for x := leftBuffer; x < rightBuffer; x++ {
|
||||
displayText = append(displayText, fileRunes[x])
|
||||
}
|
||||
// if there is more text to the right of the right-most
|
||||
// column in the tab bar text, then indicate there are more
|
||||
// tabs to the right by displaying a "+"
|
||||
if rightBuffer < len(fileRunes)-1 {
|
||||
displayText = append(displayText, '+')
|
||||
}
|
||||
|
||||
// now store the offset from zero of the left-most text
|
||||
// that is being displayed. This is to ensure that when
|
||||
// clicking on the tab bar, the correct tab gets selected.
|
||||
tabBarOffset = leftBuffer
|
||||
|
||||
// use the constructed buffer as the display buffer to print
|
||||
// onscreen.
|
||||
fileRunes = displayText
|
||||
} else {
|
||||
tabBarOffset = 0
|
||||
}
|
||||
|
||||
// iterate over the width of the terminal display and for each column,
|
||||
// write a character into the tab display area with the appropriate style.
|
||||
for x := 0; x < w; x++ {
|
||||
if x < len(fileRunes) {
|
||||
screen.SetContent(x, 0, fileRunes[x], nil, tabBarStyle)
|
||||
|
||||
@@ -59,6 +59,12 @@ func Max(a, b int) int {
|
||||
return b
|
||||
}
|
||||
|
||||
func FSize(f *os.File) int64 {
|
||||
fi, _ := f.Stat()
|
||||
// get the size
|
||||
return fi.Size()
|
||||
}
|
||||
|
||||
// IsWordChar returns whether or not the string is a 'word character'
|
||||
// If it is a unicode character, then it does not match
|
||||
// Word characters are defined as [A-Za-z0-9_]
|
||||
@@ -76,6 +82,16 @@ func IsWhitespace(c rune) bool {
|
||||
return c == ' ' || c == '\t' || c == '\n'
|
||||
}
|
||||
|
||||
// IsStrWhitespace returns true if the given string is all whitespace
|
||||
func IsStrWhitespace(str string) bool {
|
||||
for _, c := range str {
|
||||
if !IsWhitespace(c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Contains returns whether or not a string array contains a given string
|
||||
func Contains(list []string, a string) bool {
|
||||
for _, b := range list {
|
||||
|
||||
@@ -6,17 +6,21 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mattn/go-runewidth"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/zyedidia/tcell"
|
||||
)
|
||||
|
||||
type ViewType int
|
||||
type ViewType struct {
|
||||
kind int
|
||||
readonly bool // The file cannot be edited
|
||||
scratch bool // The file cannot be saved
|
||||
}
|
||||
|
||||
const (
|
||||
vtDefault ViewType = iota
|
||||
vtHelp
|
||||
vtLog
|
||||
var (
|
||||
vtDefault = ViewType{0, false, false}
|
||||
vtHelp = ViewType{1, true, true}
|
||||
vtLog = ViewType{2, true, true}
|
||||
vtScratch = ViewType{3, false, true}
|
||||
)
|
||||
|
||||
// The View struct stores information about a view into a buffer.
|
||||
@@ -84,8 +88,7 @@ type View struct {
|
||||
// Same here, just to keep track for mouse move events
|
||||
tripleClick bool
|
||||
|
||||
// Syntax highlighting matches
|
||||
matches SyntaxMatches
|
||||
cellview *CellView
|
||||
|
||||
splitNode *LeafNode
|
||||
}
|
||||
@@ -105,6 +108,7 @@ func NewViewWidthHeight(buf *Buffer, w, h int) *View {
|
||||
|
||||
v.Width = w
|
||||
v.Height = h
|
||||
v.cellview = new(CellView)
|
||||
|
||||
v.ToggleTabbar()
|
||||
|
||||
@@ -183,9 +187,9 @@ func (v *View) ScrollUp(n int) {
|
||||
// ScrollDown scrolls the view down n lines (if possible)
|
||||
func (v *View) ScrollDown(n int) {
|
||||
// Try to scroll by n but if it would overflow, scroll by 1
|
||||
if v.Topline+n <= v.Buf.NumLines-v.Height {
|
||||
if v.Topline+n <= v.Buf.NumLines {
|
||||
v.Topline += n
|
||||
} else if v.Topline < v.Buf.NumLines-v.Height {
|
||||
} else if v.Topline < v.Buf.NumLines-1 {
|
||||
v.Topline++
|
||||
}
|
||||
}
|
||||
@@ -195,18 +199,19 @@ func (v *View) ScrollDown(n int) {
|
||||
// causing them to lose the unsaved changes
|
||||
func (v *View) CanClose() bool {
|
||||
if v.Type == vtDefault && v.Buf.IsModified {
|
||||
var char rune
|
||||
var choice bool
|
||||
var canceled bool
|
||||
if v.Buf.Settings["autosave"].(bool) {
|
||||
char = 'y'
|
||||
choice = true
|
||||
} else {
|
||||
char, canceled = messenger.LetterPrompt("Save changes to "+v.Buf.GetName()+" before closing? (y,n,esc) ", 'y', 'n')
|
||||
choice, canceled = messenger.YesNoPrompt("Save changes to " + v.Buf.GetName() + " before closing? (y,n,esc) ")
|
||||
}
|
||||
if !canceled {
|
||||
if char == 'y' {
|
||||
//if char == 'y' {
|
||||
if choice {
|
||||
v.Save(true)
|
||||
return true
|
||||
} else if char == 'n' {
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -230,8 +235,6 @@ func (v *View) OpenBuffer(buf *Buffer) {
|
||||
v.Center(false)
|
||||
v.messages = make(map[string][]GutterMessage)
|
||||
|
||||
v.matches = Match(v)
|
||||
|
||||
// Set mouseReleased to true because we assume the mouse is not being pressed when
|
||||
// the editor is opened
|
||||
v.mouseReleased = true
|
||||
@@ -243,15 +246,22 @@ func (v *View) Open(filename string) {
|
||||
home, _ := homedir.Dir()
|
||||
filename = strings.Replace(filename, "~", home, 1)
|
||||
file, err := os.Open(filename)
|
||||
fileInfo, _ := os.Stat(filename)
|
||||
|
||||
if err == nil && fileInfo.IsDir() {
|
||||
messenger.Error(filename, " is a directory")
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
var buf *Buffer
|
||||
if err != nil {
|
||||
messenger.Message(err.Error())
|
||||
// File does not exist -- create an empty buffer with that name
|
||||
buf = NewBuffer(strings.NewReader(""), filename)
|
||||
buf = NewBufferFromString("", filename)
|
||||
} else {
|
||||
buf = NewBuffer(file, filename)
|
||||
buf = NewBuffer(file, FSize(file), filename)
|
||||
}
|
||||
v.OpenBuffer(buf)
|
||||
}
|
||||
@@ -269,7 +279,6 @@ func (v *View) ReOpen() {
|
||||
screen.Clear()
|
||||
v.Buf.ReOpen()
|
||||
v.Relocate()
|
||||
v.matches = Match(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,9 +459,6 @@ func (v *View) HandleEvent(event tcell.Event) {
|
||||
v.Buf.CheckModTime()
|
||||
|
||||
switch e := event.(type) {
|
||||
case *tcell.EventResize:
|
||||
// Window resized
|
||||
tabs[v.TabNum].Resize()
|
||||
case *tcell.EventKey:
|
||||
// Check first if input is a key binding, if it is we 'eat' the input and don't insert a rune
|
||||
isBinding := false
|
||||
@@ -599,6 +605,12 @@ func (v *View) HandleEvent(event tcell.Event) {
|
||||
|
||||
if relocate {
|
||||
v.Relocate()
|
||||
// We run relocate again because there's a bug with relocating with softwrap
|
||||
// when for example you jump to the bottom of the buffer and it tries to
|
||||
// calculate where to put the topline so that the bottom line is at the bottom
|
||||
// of the terminal and it runs into problems with visual lines vs real lines.
|
||||
// This is (hopefully) a temporary solution
|
||||
v.Relocate()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -638,7 +650,7 @@ func (v *View) openHelp(helpPage string) {
|
||||
if data, err := FindRuntimeFile(RTHelp, helpPage).Data(); err != nil {
|
||||
TermMessage("Unable to load help text", helpPage, "\n", err)
|
||||
} else {
|
||||
helpBuffer := NewBuffer(strings.NewReader(string(data)), helpPage+".md")
|
||||
helpBuffer := NewBufferFromString(string(data), helpPage+".md")
|
||||
helpBuffer.name = "Help"
|
||||
|
||||
if v.Type == vtHelp {
|
||||
@@ -650,34 +662,23 @@ func (v *View) openHelp(helpPage string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (v *View) drawCell(x, y int, ch rune, combc []rune, style tcell.Style) {
|
||||
if x >= v.x && x < v.x+v.Width && y >= v.y && y < v.y+v.Height {
|
||||
screen.SetContent(x, y, ch, combc, style)
|
||||
}
|
||||
}
|
||||
|
||||
// DisplayView renders the view to the screen
|
||||
func (v *View) DisplayView() {
|
||||
if v.Buf.Settings["softwrap"].(bool) && v.leftCol != 0 {
|
||||
v.leftCol = 0
|
||||
}
|
||||
|
||||
if v.Type == vtLog {
|
||||
// Log views should always follow the cursor...
|
||||
v.Relocate()
|
||||
}
|
||||
|
||||
if v.Buf.Settings["syntax"].(bool) {
|
||||
v.matches = Match(v)
|
||||
}
|
||||
|
||||
// The charNum we are currently displaying
|
||||
// starts at the start of the viewport
|
||||
charNum := Loc{0, v.Topline}
|
||||
|
||||
// Convert the length of buffer to a string, and get the length of the string
|
||||
// We are going to have to offset by that amount
|
||||
maxLineLength := len(strconv.Itoa(v.Buf.NumLines))
|
||||
// We need to know the string length of the largest line number
|
||||
// so we can pad appropriately when displaying line numbers
|
||||
maxLineNumLength := len(strconv.Itoa(v.Buf.NumLines))
|
||||
|
||||
if v.Buf.Settings["ruler"] == true {
|
||||
// + 1 for the little space after the line number
|
||||
v.lineNumOffset = maxLineLength + 1
|
||||
v.lineNumOffset = maxLineNumLength + 1
|
||||
} else {
|
||||
v.lineNumOffset = 0
|
||||
}
|
||||
@@ -693,44 +694,52 @@ func (v *View) DisplayView() {
|
||||
v.lineNumOffset += 2
|
||||
}
|
||||
|
||||
divider := 0
|
||||
if v.x != 0 {
|
||||
// One space for the extra split divider
|
||||
v.lineNumOffset++
|
||||
divider = 1
|
||||
}
|
||||
|
||||
// These represent the current screen coordinates
|
||||
screenX, screenY := v.x, v.y-1
|
||||
xOffset := v.x + v.lineNumOffset
|
||||
yOffset := v.y
|
||||
|
||||
highlightStyle := defStyle
|
||||
curLineN := 0
|
||||
height := v.Height
|
||||
width := v.Width
|
||||
left := v.leftCol
|
||||
top := v.Topline
|
||||
|
||||
// ViewLine is the current line from the top of the viewport
|
||||
for viewLine := 0; viewLine < v.Height; viewLine++ {
|
||||
screenY++
|
||||
screenX = v.x
|
||||
v.cellview.Draw(v.Buf, top, height, left, width-v.lineNumOffset)
|
||||
|
||||
// This is the current line number of the buffer that we are drawing
|
||||
curLineN = viewLine + v.Topline
|
||||
|
||||
if screenY-v.y >= v.Height {
|
||||
break
|
||||
screenX := v.x
|
||||
realLineN := top - 1
|
||||
visualLineN := 0
|
||||
var line []*Char
|
||||
for visualLineN, line = range v.cellview.lines {
|
||||
var firstChar *Char
|
||||
if len(line) > 0 {
|
||||
firstChar = line[0]
|
||||
}
|
||||
|
||||
if v.x != 0 {
|
||||
// Draw the split divider
|
||||
v.drawCell(screenX, screenY, '|', nil, defStyle.Reverse(true))
|
||||
screenX++
|
||||
}
|
||||
|
||||
// If the buffer is smaller than the view height we have to clear all this space
|
||||
if curLineN >= v.Buf.NumLines {
|
||||
for i := screenX; i < v.x+v.Width; i++ {
|
||||
v.drawCell(i, screenY, ' ', nil, defStyle)
|
||||
var softwrapped bool
|
||||
if firstChar != nil {
|
||||
if firstChar.realLoc.Y == realLineN {
|
||||
softwrapped = true
|
||||
}
|
||||
|
||||
continue
|
||||
realLineN = firstChar.realLoc.Y
|
||||
} else {
|
||||
realLineN++
|
||||
}
|
||||
line := v.Buf.Line(curLineN)
|
||||
|
||||
colorcolumn := int(v.Buf.Settings["colorcolumn"].(float64))
|
||||
if colorcolumn != 0 {
|
||||
style := GetColor("color-column")
|
||||
fg, _, _ := style.Decompose()
|
||||
st := defStyle.Background(fg)
|
||||
screen.SetContent(xOffset+colorcolumn, yOffset+visualLineN, ' ', nil, st)
|
||||
}
|
||||
|
||||
screenX = v.x
|
||||
|
||||
// If there are gutter messages we need to display the '>>' symbol here
|
||||
if hasGutterMessages {
|
||||
@@ -738,7 +747,7 @@ func (v *View) DisplayView() {
|
||||
msgOnLine := false
|
||||
for k := range v.messages {
|
||||
for _, msg := range v.messages[k] {
|
||||
if msg.lineNum == curLineN {
|
||||
if msg.lineNum == realLineN {
|
||||
msgOnLine = true
|
||||
gutterStyle := defStyle
|
||||
switch msg.kind {
|
||||
@@ -755,11 +764,11 @@ func (v *View) DisplayView() {
|
||||
gutterStyle = style
|
||||
}
|
||||
}
|
||||
v.drawCell(screenX, screenY, '>', nil, gutterStyle)
|
||||
screen.SetContent(screenX, yOffset+visualLineN, '>', nil, gutterStyle)
|
||||
screenX++
|
||||
v.drawCell(screenX, screenY, '>', nil, gutterStyle)
|
||||
screen.SetContent(screenX, yOffset+visualLineN, '>', nil, gutterStyle)
|
||||
screenX++
|
||||
if v.Cursor.Y == curLineN && !messenger.hasPrompt {
|
||||
if v.Cursor.Y == realLineN && !messenger.hasPrompt {
|
||||
messenger.Message(msg.msg)
|
||||
messenger.gutterMessage = true
|
||||
}
|
||||
@@ -768,11 +777,11 @@ func (v *View) DisplayView() {
|
||||
}
|
||||
// If there is no message on this line we just display an empty offset
|
||||
if !msgOnLine {
|
||||
v.drawCell(screenX, screenY, ' ', nil, defStyle)
|
||||
screen.SetContent(screenX, yOffset+visualLineN, ' ', nil, defStyle)
|
||||
screenX++
|
||||
v.drawCell(screenX, screenY, ' ', nil, defStyle)
|
||||
screen.SetContent(screenX, yOffset+visualLineN, ' ', nil, defStyle)
|
||||
screenX++
|
||||
if v.Cursor.Y == curLineN && messenger.gutterMessage {
|
||||
if v.Cursor.Y == realLineN && messenger.gutterMessage {
|
||||
messenger.Reset()
|
||||
messenger.gutterMessage = false
|
||||
}
|
||||
@@ -786,202 +795,149 @@ func (v *View) DisplayView() {
|
||||
lineNumStyle = style
|
||||
}
|
||||
if style, ok := colorscheme["current-line-number"]; ok {
|
||||
if curLineN == v.Cursor.Y && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() {
|
||||
if realLineN == v.Cursor.Y && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() {
|
||||
lineNumStyle = style
|
||||
}
|
||||
}
|
||||
|
||||
lineNum := strconv.Itoa(curLineN + 1)
|
||||
lineNum := strconv.Itoa(realLineN + 1)
|
||||
|
||||
// Write the spaces before the line number if necessary
|
||||
for i := 0; i < maxLineLength-len(lineNum); i++ {
|
||||
v.drawCell(screenX, screenY, ' ', nil, lineNumStyle)
|
||||
for i := 0; i < maxLineNumLength-len(lineNum); i++ {
|
||||
screen.SetContent(screenX+divider, yOffset+visualLineN, ' ', nil, lineNumStyle)
|
||||
screenX++
|
||||
}
|
||||
// Write the actual line number
|
||||
for _, ch := range lineNum {
|
||||
v.drawCell(screenX, screenY, ch, nil, lineNumStyle)
|
||||
screenX++
|
||||
if softwrapped && visualLineN != 0 {
|
||||
// Pad without the line number because it was written on the visual line before
|
||||
for range lineNum {
|
||||
screen.SetContent(screenX+divider, yOffset+visualLineN, ' ', nil, lineNumStyle)
|
||||
screenX++
|
||||
}
|
||||
} else {
|
||||
// Write the actual line number
|
||||
for _, ch := range lineNum {
|
||||
screen.SetContent(screenX+divider, yOffset+visualLineN, ch, nil, lineNumStyle)
|
||||
screenX++
|
||||
}
|
||||
}
|
||||
|
||||
// Write the extra space
|
||||
v.drawCell(screenX, screenY, ' ', nil, lineNumStyle)
|
||||
screen.SetContent(screenX+divider, yOffset+visualLineN, ' ', nil, lineNumStyle)
|
||||
screenX++
|
||||
}
|
||||
|
||||
// Now we actually draw the line
|
||||
colN := 0
|
||||
strWidth := 0
|
||||
tabSize := int(v.Buf.Settings["tabsize"].(float64))
|
||||
for _, ch := range line {
|
||||
if v.Buf.Settings["softwrap"].(bool) {
|
||||
if screenX-v.x >= v.Width {
|
||||
screenY++
|
||||
var lastChar *Char
|
||||
cursorSet := false
|
||||
for _, char := range line {
|
||||
if char != nil {
|
||||
lineStyle := char.style
|
||||
|
||||
x := 0
|
||||
if hasGutterMessages {
|
||||
v.drawCell(v.x+x, screenY, ' ', nil, defStyle)
|
||||
x++
|
||||
v.drawCell(v.x+x, screenY, ' ', nil, defStyle)
|
||||
x++
|
||||
}
|
||||
for i := 0; i < v.lineNumOffset; i++ {
|
||||
screen.SetContent(v.x+i+x, screenY, ' ', nil, lineNumStyle)
|
||||
}
|
||||
screenX = v.x + v.lineNumOffset
|
||||
}
|
||||
}
|
||||
|
||||
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN && colN == v.Cursor.X {
|
||||
v.DisplayCursor(screenX-v.leftCol, screenY)
|
||||
}
|
||||
|
||||
lineStyle := defStyle
|
||||
|
||||
if v.Buf.Settings["syntax"].(bool) {
|
||||
// Syntax highlighting is enabled
|
||||
highlightStyle = v.matches[viewLine][colN]
|
||||
}
|
||||
|
||||
if v.Cursor.HasSelection() &&
|
||||
(charNum.GreaterEqual(v.Cursor.CurSelection[0]) && charNum.LessThan(v.Cursor.CurSelection[1]) ||
|
||||
charNum.LessThan(v.Cursor.CurSelection[0]) && charNum.GreaterEqual(v.Cursor.CurSelection[1])) {
|
||||
// The current character is selected
|
||||
lineStyle = defStyle.Reverse(true)
|
||||
|
||||
if style, ok := colorscheme["selection"]; ok {
|
||||
lineStyle = style
|
||||
}
|
||||
} else {
|
||||
lineStyle = highlightStyle
|
||||
}
|
||||
|
||||
// We need to display the background of the linestyle with the correct color if cursorline is enabled
|
||||
// and this is the current view and there is no selection on this line and the cursor is on this line
|
||||
if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN {
|
||||
if style, ok := colorscheme["cursor-line"]; ok {
|
||||
colorcolumn := int(v.Buf.Settings["colorcolumn"].(float64))
|
||||
if colorcolumn != 0 && char.visualLoc.X == colorcolumn {
|
||||
style := GetColor("color-column")
|
||||
fg, _, _ := style.Decompose()
|
||||
lineStyle = lineStyle.Background(fg)
|
||||
}
|
||||
}
|
||||
|
||||
if ch == '\t' {
|
||||
// If the character we are displaying is a tab, we need to do a bunch of special things
|
||||
|
||||
// First the user may have configured an `indent-char` to be displayed to show that this
|
||||
// is a tab character
|
||||
lineIndentStyle := defStyle
|
||||
if style, ok := colorscheme["indent-char"]; ok && v.Buf.Settings["indentchar"].(string) != " " {
|
||||
lineIndentStyle = style
|
||||
}
|
||||
charLoc := char.realLoc
|
||||
if v.Cursor.HasSelection() &&
|
||||
(charNum.GreaterEqual(v.Cursor.CurSelection[0]) && charNum.LessThan(v.Cursor.CurSelection[1]) ||
|
||||
charNum.LessThan(v.Cursor.CurSelection[0]) && charNum.GreaterEqual(v.Cursor.CurSelection[1])) {
|
||||
|
||||
lineIndentStyle = defStyle.Reverse(true)
|
||||
(charLoc.GreaterEqual(v.Cursor.CurSelection[0]) && charLoc.LessThan(v.Cursor.CurSelection[1]) ||
|
||||
charLoc.LessThan(v.Cursor.CurSelection[0]) && charLoc.GreaterEqual(v.Cursor.CurSelection[1])) {
|
||||
// The current character is selected
|
||||
lineStyle = defStyle.Reverse(true)
|
||||
|
||||
if style, ok := colorscheme["selection"]; ok {
|
||||
lineIndentStyle = style
|
||||
lineStyle = style
|
||||
}
|
||||
}
|
||||
if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN {
|
||||
if style, ok := colorscheme["cursor-line"]; ok {
|
||||
fg, _, _ := style.Decompose()
|
||||
lineIndentStyle = lineIndentStyle.Background(fg)
|
||||
}
|
||||
|
||||
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
|
||||
v.Cursor.Y == char.realLoc.Y && v.Cursor.X == char.realLoc.X && !cursorSet {
|
||||
screen.ShowCursor(xOffset+char.visualLoc.X, yOffset+char.visualLoc.Y)
|
||||
cursorSet = true
|
||||
}
|
||||
// Here we get the indent char
|
||||
indentChar := []rune(v.Buf.Settings["indentchar"].(string))
|
||||
if screenX-v.x-v.leftCol >= v.lineNumOffset {
|
||||
v.drawCell(screenX-v.leftCol, screenY, indentChar[0], nil, lineIndentStyle)
|
||||
|
||||
if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num &&
|
||||
!v.Cursor.HasSelection() && v.Cursor.Y == realLineN {
|
||||
style := GetColor("cursor-line")
|
||||
fg, _, _ := style.Decompose()
|
||||
lineStyle = lineStyle.Background(fg)
|
||||
}
|
||||
// Now the tab has to be displayed as a bunch of spaces
|
||||
visLoc := strWidth
|
||||
remainder := tabSize - (visLoc % tabSize)
|
||||
for i := 0; i < remainder-1; i++ {
|
||||
screenX++
|
||||
if screenX-v.x-v.leftCol >= v.lineNumOffset {
|
||||
v.drawCell(screenX-v.leftCol, screenY, ' ', nil, lineStyle)
|
||||
}
|
||||
}
|
||||
strWidth += remainder
|
||||
} else if runewidth.RuneWidth(ch) > 1 {
|
||||
if screenX-v.x-v.leftCol >= v.lineNumOffset {
|
||||
v.drawCell(screenX, screenY, ch, nil, lineStyle)
|
||||
}
|
||||
for i := 0; i < runewidth.RuneWidth(ch)-1; i++ {
|
||||
screenX++
|
||||
if screenX-v.x-v.leftCol >= v.lineNumOffset {
|
||||
v.drawCell(screenX-v.leftCol, screenY, '<', nil, lineStyle)
|
||||
}
|
||||
}
|
||||
strWidth += StringWidth(string(ch), tabSize)
|
||||
} else {
|
||||
if screenX-v.x-v.leftCol >= v.lineNumOffset {
|
||||
v.drawCell(screenX-v.leftCol, screenY, ch, nil, lineStyle)
|
||||
}
|
||||
strWidth += StringWidth(string(ch), tabSize)
|
||||
|
||||
screen.SetContent(xOffset+char.visualLoc.X, yOffset+char.visualLoc.Y, char.drawChar, nil, lineStyle)
|
||||
|
||||
lastChar = char
|
||||
}
|
||||
charNum = charNum.Move(1, v.Buf)
|
||||
screenX++
|
||||
colN++
|
||||
}
|
||||
// Here we are at a newline
|
||||
|
||||
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN && colN == v.Cursor.X {
|
||||
v.DisplayCursor(screenX-v.leftCol, screenY)
|
||||
}
|
||||
|
||||
// The newline may be selected, in which case we should draw the selection style
|
||||
// with a space to represent it
|
||||
lastX := 0
|
||||
var realLoc Loc
|
||||
var visualLoc Loc
|
||||
var cx, cy int
|
||||
if lastChar != nil {
|
||||
lastX = xOffset + lastChar.visualLoc.X + lastChar.width
|
||||
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
|
||||
v.Cursor.Y == lastChar.realLoc.Y && v.Cursor.X == lastChar.realLoc.X+1 {
|
||||
screen.ShowCursor(lastX, yOffset+lastChar.visualLoc.Y)
|
||||
cx, cy = lastX, yOffset+lastChar.visualLoc.Y
|
||||
}
|
||||
realLoc = Loc{lastChar.realLoc.X, realLineN}
|
||||
visualLoc = Loc{lastX - xOffset, lastChar.visualLoc.Y}
|
||||
} else if len(line) == 0 {
|
||||
if tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() &&
|
||||
v.Cursor.Y == realLineN {
|
||||
screen.ShowCursor(xOffset, yOffset+visualLineN)
|
||||
cx, cy = xOffset, yOffset+visualLineN
|
||||
}
|
||||
lastX = xOffset
|
||||
realLoc = Loc{0, realLineN}
|
||||
visualLoc = Loc{0, visualLineN}
|
||||
}
|
||||
|
||||
if v.Cursor.HasSelection() &&
|
||||
(charNum.GreaterEqual(v.Cursor.CurSelection[0]) && charNum.LessThan(v.Cursor.CurSelection[1]) ||
|
||||
charNum.LessThan(v.Cursor.CurSelection[0]) && charNum.GreaterEqual(v.Cursor.CurSelection[1])) {
|
||||
|
||||
(realLoc.GreaterEqual(v.Cursor.CurSelection[0]) && realLoc.LessThan(v.Cursor.CurSelection[1]) ||
|
||||
realLoc.LessThan(v.Cursor.CurSelection[0]) && realLoc.GreaterEqual(v.Cursor.CurSelection[1])) {
|
||||
// The current character is selected
|
||||
selectStyle := defStyle.Reverse(true)
|
||||
|
||||
if style, ok := colorscheme["selection"]; ok {
|
||||
selectStyle = style
|
||||
}
|
||||
v.drawCell(screenX, screenY, ' ', nil, selectStyle)
|
||||
screenX++
|
||||
screen.SetContent(xOffset+visualLoc.X, yOffset+visualLoc.Y, ' ', nil, selectStyle)
|
||||
}
|
||||
|
||||
charNum = charNum.Move(1, v.Buf)
|
||||
if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num &&
|
||||
!v.Cursor.HasSelection() && v.Cursor.Y == realLineN {
|
||||
for i := lastX; i < xOffset+v.Width; i++ {
|
||||
style := GetColor("cursor-line")
|
||||
fg, _, _ := style.Decompose()
|
||||
style = style.Background(fg)
|
||||
if !(tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && i == cx && yOffset+visualLineN == cy) {
|
||||
screen.SetContent(i, yOffset+visualLineN, ' ', nil, style)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < v.Width; i++ {
|
||||
lineStyle := defStyle
|
||||
if v.Buf.Settings["cursorline"].(bool) && tabs[curTab].CurView == v.Num && !v.Cursor.HasSelection() && v.Cursor.Y == curLineN {
|
||||
if style, ok := colorscheme["cursor-line"]; ok {
|
||||
fg, _, _ := style.Decompose()
|
||||
lineStyle = lineStyle.Background(fg)
|
||||
}
|
||||
}
|
||||
if screenX-v.x-v.leftCol+i >= v.lineNumOffset {
|
||||
colorcolumn := int(v.Buf.Settings["colorcolumn"].(float64))
|
||||
if colorcolumn != 0 && screenX-v.lineNumOffset+i == colorcolumn-1 {
|
||||
if style, ok := colorscheme["color-column"]; ok {
|
||||
fg, _, _ := style.Decompose()
|
||||
lineStyle = lineStyle.Background(fg)
|
||||
}
|
||||
}
|
||||
v.drawCell(screenX-v.leftCol+i, screenY, ' ', nil, lineStyle)
|
||||
}
|
||||
if divider != 0 {
|
||||
dividerStyle := defStyle
|
||||
if style, ok := colorscheme["divider"]; ok {
|
||||
dividerStyle = style
|
||||
}
|
||||
for i := 0; i < v.Height; i++ {
|
||||
screen.SetContent(v.x, yOffset+i, '|', nil, dividerStyle.Reverse(true))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DisplayCursor draws the current buffer's cursor to the screen
|
||||
func (v *View) DisplayCursor(x, y int) {
|
||||
// screen.ShowCursor(v.x+v.Cursor.GetVisualX()+v.lineNumOffset-v.leftCol, y)
|
||||
screen.ShowCursor(x, y)
|
||||
}
|
||||
|
||||
// Display renders the view, the cursor, and statusline
|
||||
func (v *View) Display() {
|
||||
if globalSettings["termtitle"].(bool) {
|
||||
screen.SetTitle("micro: " + v.Buf.GetName())
|
||||
}
|
||||
v.DisplayView()
|
||||
// Don't draw the cursor if it is out of the viewport or if it has a selection
|
||||
if (v.Cursor.Y-v.Topline < 0 || v.Cursor.Y-v.Topline > v.Height-1) || v.Cursor.HasSelection() {
|
||||
if (v.Cursor.Y-v.Topline < 0 || v.Cursor.Y-v.Topline > v.Height-1) || (v.Cursor.HasSelection() && v.Num == tabs[curTab].CurView) {
|
||||
screen.HideCursor()
|
||||
}
|
||||
_, screenH := screen.Size()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Runtime files for Micro
|
||||
|
||||
This directory will be embedded in the Go binary for portability, but it may just as well be put in `~/.config/micro`. If you would like to make your own colorschemes
|
||||
and syntax files, you can put in in `~/.config/micro/colorschemes` and `~/.config/micro/syntax` respectively.
|
||||
and syntax files, you can put them in `~/.config/micro/colorschemes` and `~/.config/micro/syntax` respectively.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ color-link identifier "#F9EE98,#1D1F21"
|
||||
color-link constant "#FF73FD,#1D1F21"
|
||||
color-link constant.string "#A8FF60,#1D1F21"
|
||||
color-link statement "#96CBFE,#1D1F21"
|
||||
color-link symbol "#96CBFE,#1DF121"
|
||||
color-link symbol "#96CBFE,#1D1F21"
|
||||
color-link preproc "#62B1FE,#1D1F21"
|
||||
color-link type "#C6C5FE,#1D1F21"
|
||||
color-link special "#A6E22E,#1D1F21"
|
||||
@@ -12,6 +12,7 @@ color-link underlined "#D33682,#1D1F21"
|
||||
color-link error "bold #FF4444,#1D1F21"
|
||||
color-link todo "bold #FF8844,#1D1F21"
|
||||
color-link statusline "#1D1F21,#C5C8C6"
|
||||
color-link tabbar "#1D1F21,#C5C8C6"
|
||||
color-link indent-char "#505050,#1D1F21"
|
||||
color-link line-number "#656866,#232526"
|
||||
color-link current-line-number "#656866,#1D1F21"
|
||||
@@ -19,3 +20,7 @@ color-link gutter-error "#FF4444,#1D1F21"
|
||||
color-link gutter-warning "#EEEE77,#1D1F21"
|
||||
color-link cursor-line "#2D2F31"
|
||||
color-link color-column "#2D2F31"
|
||||
#color-link symbol.brackets "#96CBFE,#1D1F21"
|
||||
#No extended types (bool in C, etc.)
|
||||
#color-link type.extended "default"
|
||||
#Plain brackets
|
||||
|
||||
@@ -12,10 +12,13 @@ color-link special "167,231"
|
||||
color-link error "231, 160"
|
||||
color-link underlined "underline 241,231"
|
||||
color-link todo "246,231"
|
||||
|
||||
color-link statusline "241,254"
|
||||
color-link tabbar "241,254"
|
||||
color-link gutter-error "197,231"
|
||||
color-link gutter-warning "134,231"
|
||||
color-link line-number "246,254"
|
||||
color-link cursor-line "254"
|
||||
color-link color-column "254"
|
||||
#No extended types (bool in C, &c.) and plain brackets
|
||||
color-link type.extended "default"
|
||||
color-link symbol.brackets "default"
|
||||
40
runtime/colorschemes/cmc-16.micro
Normal file
40
runtime/colorschemes/cmc-16.micro
Normal file
@@ -0,0 +1,40 @@
|
||||
#CaptainMcClellan's personal color scheme.
|
||||
#16 colour version.
|
||||
color-link comment "bold black"
|
||||
color-link constant "cyan"
|
||||
color-link constant.bool "bold cyan"
|
||||
color-link constant.bool.true "bold green"
|
||||
color-link constant.bool.false "bold red"
|
||||
color-link constant.string "yellow"
|
||||
color-link constant.string.url "underline blue, white"
|
||||
#color-link constant.number "constant"
|
||||
color-link constant.specialChar "bold magenta"
|
||||
color-link identifier "bold red"
|
||||
color-link identifier.macro "bold red"
|
||||
color-link identifier.var "bold blue"
|
||||
#color-link identifier.class "bold green"
|
||||
color-link identifier.class "bold white"
|
||||
color-link statement "bold yellow"
|
||||
color-link symbol "red"
|
||||
color-link symbol.brackets "blue"
|
||||
color-link symbol.tag "bold blue"
|
||||
color-link symbol.tag.extended "bold green"
|
||||
color-link preproc "bold cyan"
|
||||
color-link type "green"
|
||||
color-link type.keyword "bold green"
|
||||
color-link special "magenta"
|
||||
color-link ignore "default"
|
||||
color-link error "bold ,brightred"
|
||||
color-link todo "underline black,brightyellow"
|
||||
color-link indent-char ",brightgreen"
|
||||
color-link line-number "green"
|
||||
color-link line-number.scrollbar "green"
|
||||
color-link statusline "white,blue"
|
||||
color-link tabbar "white,blue"
|
||||
color-link current-line-number "red"
|
||||
color-link current-line-number.scroller "red"
|
||||
color-link gutter-error ",red"
|
||||
color-link gutter-warning "red"
|
||||
color-link color-column "cyan"
|
||||
color-link underlined.url "underline blue, white"
|
||||
color-link divider "blue"
|
||||
37
runtime/colorschemes/cmc-paper.micro
Normal file
37
runtime/colorschemes/cmc-paper.micro
Normal file
@@ -0,0 +1,37 @@
|
||||
#CaptainMcClellan's personal color scheme.
|
||||
#Paper version
|
||||
color-link default "black,white"
|
||||
color-link comment "bold black"
|
||||
color-link constant "cyan"
|
||||
color-link constant.bool "bold cyan"
|
||||
color-link constant.bool.true "bold green"
|
||||
color-link constant.bool.false "bold red"
|
||||
color-link constant.string "bold yellow"
|
||||
color-link constant.string.url "underline blue, white"
|
||||
color-link constant.number "constant"
|
||||
color-link constant.specialChar "bold magenta"
|
||||
color-link identifier "bold red"
|
||||
color-link identifier.macro "bold red"
|
||||
color-link identifier.var "bold blue"
|
||||
color-link identifier.class "bold green"
|
||||
color-link preproc "bold cyan"
|
||||
color-link statement "bold yellow"
|
||||
color-link symbol "red"
|
||||
color-link symbol.brackets "blue"
|
||||
color-link type "green"
|
||||
color-link type.keyword "bold green"
|
||||
color-link special "magenta"
|
||||
color-link ignore "default"
|
||||
color-link error ",brightred"
|
||||
color-link todo "black,brightyellow"
|
||||
color-link indent-char ",brightgreen"
|
||||
color-link line-number "green"
|
||||
color-link line-number.scrollbar "green"
|
||||
color-link statusline "white,blue"
|
||||
color-link tabbar "white,blue"
|
||||
color-link current-line-number "red"
|
||||
color-link current-line-number.scroller "red"
|
||||
color-link gutter-error ",red"
|
||||
color-link gutter-warning "red"
|
||||
color-link color-column "cyan"
|
||||
color-link underlined.url "underline blue, white"
|
||||
36
runtime/colorschemes/cmc-tc.micro
Normal file
36
runtime/colorschemes/cmc-tc.micro
Normal file
@@ -0,0 +1,36 @@
|
||||
#CaptainMcClellan's personal colour scheme.
|
||||
#Full colour edition.
|
||||
color-link default "#aaaaaa,#1e2124"
|
||||
color-link comment "bold #555555"
|
||||
color-link constant "#008888"
|
||||
#color-link constant.string "#888800"
|
||||
color-link constant.string "#a85700"
|
||||
color-link constant.specialChar "bold #ccccff"
|
||||
color-link identifier "bold #e34234"
|
||||
color-link identifier.macro "bold #e34234"
|
||||
color-link identifier.var "bold #5757ff"
|
||||
color-link identifier.class "bold #ffffff"
|
||||
color-link statement "bold #ffff55"
|
||||
color-link symbol "#722f37"
|
||||
color-link symbol.brackets "#4169e1"
|
||||
color-link symbol.tag "#5757ff"
|
||||
color-link preproc "bold #55ffff"
|
||||
color-link type "#3eb489"
|
||||
color-link type.keyword "bold #bdecb6"
|
||||
color-link special "#b57edc"
|
||||
color-link ignore "default"
|
||||
color-link error "bold ,#e34234"
|
||||
color-link todo "bold underline #888888,#f26522"
|
||||
color-link indent-char ",#bdecb6"
|
||||
color-link line-number "#bdecb6,#36393e"
|
||||
color-link line-number.scrollbar "#3eb489"
|
||||
color-link statusline "#aaaaaa,#8a496b"
|
||||
color-link tabbar "#aaaaaa,#8a496b"
|
||||
color-link current-line-number "bold #e34234,#424549"
|
||||
color-link current-line-number.scroller "red"
|
||||
color-link gutter-error ",#e34234"
|
||||
color-link gutter-warning "#e34234"
|
||||
color-link color-column "#f26522"
|
||||
color-link constant.bool "bold #55ffff"
|
||||
color-link constant.bool.true "bold #85ff85"
|
||||
color-link constant.bool.false "bold #ff8585"
|
||||
25
runtime/colorschemes/codeblocks-paper.micro
Normal file
25
runtime/colorschemes/codeblocks-paper.micro
Normal file
@@ -0,0 +1,25 @@
|
||||
#A colorscheme based on Code::Blocks IDE
|
||||
#but with a white background.
|
||||
color-link default "black,white"
|
||||
color-link comment "bold black"
|
||||
color-link constant "blue"
|
||||
color-link constant.number "bold magenta"
|
||||
color-link constant.string "bold blue"
|
||||
color-link identifier "black"
|
||||
color-link preproc "green"
|
||||
color-link statement "blue"
|
||||
color-link symbol "red"
|
||||
color-link symbol.brackets "blue"
|
||||
color-link type "blue"
|
||||
color-link special "magenta"
|
||||
color-link ignore "default"
|
||||
color-link error "bold white,brightred"
|
||||
color-link todo "bold black,brightyellow"
|
||||
color-link indent-char "bold black"
|
||||
color-link line-number "black,white"
|
||||
color-link statusline "white,red"
|
||||
color-link tabbar "white,red"
|
||||
color-link current-line-number "red,black"
|
||||
color-link gutter-error ",red"
|
||||
color-link gutter-warning "red"
|
||||
color-link color-column "black"
|
||||
23
runtime/colorschemes/codeblocks.micro
Normal file
23
runtime/colorschemes/codeblocks.micro
Normal file
@@ -0,0 +1,23 @@
|
||||
#Theme based on Code::Blocks IDE's default syntax highlighting.
|
||||
color-link comment "bold black"
|
||||
color-link constant "blue"
|
||||
color-link constant.string "bold blue"
|
||||
color-link constant.number "bold magenta"
|
||||
color-link identifier "default"
|
||||
color-link preproc "green"
|
||||
color-link statement "blue"
|
||||
color-link symbol "red"
|
||||
color-link symbol.brackets "blue"
|
||||
color-link type "blue"
|
||||
color-link special "magenta"
|
||||
color-link ignore "default"
|
||||
color-link error ",brightred"
|
||||
color-link todo "bold black,brightyellow"
|
||||
color-link indent-char "bold black"
|
||||
color-link line-number "black,white"
|
||||
color-link statusline "white,red"
|
||||
color-link tabbar "white,red"
|
||||
color-link current-line-number "red"
|
||||
color-link gutter-error ",red"
|
||||
color-link gutter-warning "red"
|
||||
color-link color-column "white"
|
||||
@@ -14,6 +14,7 @@ color-link underlined "#D33682,#282828"
|
||||
color-link error "bold #CB4B16,#282828"
|
||||
color-link todo "bold #D33682,#282828"
|
||||
color-link statusline "#282828,#F8F8F2"
|
||||
color-link tabbar "#282828,#f8f8f2"
|
||||
color-link indent-char "#505050,#282828"
|
||||
color-link line-number "#AAAAAA,#323232"
|
||||
color-link current-line-number "#AAAAAA,#282828"
|
||||
@@ -21,3 +22,6 @@ color-link gutter-error "#CB4B16,#282828"
|
||||
color-link gutter-warning "#E6DB74,#282828"
|
||||
color-link cursor-line "#323232"
|
||||
color-link color-column "#323232"
|
||||
#No extended types; plain brackets
|
||||
color-link type.extended "default"
|
||||
color-link symbol.brackets "default"
|
||||
|
||||
30
runtime/colorschemes/flamepoint-tc.micro
Normal file
30
runtime/colorschemes/flamepoint-tc.micro
Normal file
@@ -0,0 +1,30 @@
|
||||
#Flamepoint theme
|
||||
#By CaptainMcClellan
|
||||
color-link default ""
|
||||
color-link comment ""
|
||||
color-link constant ""
|
||||
color-link constant.bool ""
|
||||
color-link constant.bool.true ""
|
||||
color-link constant.bool.false ""
|
||||
color-link constant.number ""
|
||||
color-link constant.specialChar ""
|
||||
color-link constant.string ""
|
||||
color-link constant.string.url "underline"
|
||||
color-link identifier ""
|
||||
color-link identifier.var ""
|
||||
color-link preproc ""
|
||||
color-link special ""
|
||||
color-link statement ""
|
||||
color-link symbol ""
|
||||
color-link symbol.brackets ""
|
||||
color-link symbol.tag ""
|
||||
color-link type ""
|
||||
color-link type.keyword ""
|
||||
color-link error ""
|
||||
color-link todo ""
|
||||
color-link cursor-line ""
|
||||
color-link statusline ""
|
||||
color-link tabbar ""
|
||||
color-link color-column ""
|
||||
color-link gutter-error ""
|
||||
color-link gutter-warning ""
|
||||
1
runtime/colorschemes/funky-cactus-tc.micro
Normal file
1
runtime/colorschemes/funky-cactus-tc.micro
Normal file
@@ -0,0 +1 @@
|
||||
#Funky Cactus theme in true colour.
|
||||
31
runtime/colorschemes/funky-cactus.micro
Normal file
31
runtime/colorschemes/funky-cactus.micro
Normal file
@@ -0,0 +1,31 @@
|
||||
#Funky Cactus theme
|
||||
color-link comment "bold black"
|
||||
color-link constant "cyan"
|
||||
color-link constant.bool "bold cyan"
|
||||
color-link constant.bool.true "bold green"
|
||||
color-link constant.bool.false "bold red"
|
||||
color-link constant.string "yellow"
|
||||
color-link constant.number "constant"
|
||||
color-link constant.specialChar "bold magenta"
|
||||
color-link identifier "bold red"
|
||||
color-link identifier.macro "bold red"
|
||||
color-link identifier.var "bold blue"
|
||||
color-link identifier.class "bold green"
|
||||
color-link preproc "bold cyan"
|
||||
color-link statement "bold yellow"
|
||||
color-link symbol "red"
|
||||
color-link symbol.brackets "blue"
|
||||
color-link type "green"
|
||||
color-link type.keyword "bold green"
|
||||
color-link special "magenta"
|
||||
color-link ignore "default"
|
||||
color-link error "bold ,brightred"
|
||||
color-link todo "underline ,brightyellow"
|
||||
color-link indent-char "bold ,brightgreen"
|
||||
color-link line-number "green"
|
||||
color-link statusline "black,green"
|
||||
color-link tabbar "black,magenta"
|
||||
color-link current-line-number "bold magenta"
|
||||
color-link gutter-error ",red"
|
||||
color-link gutter-warning "red"
|
||||
color-link color-column "bold green"
|
||||
23
runtime/colorschemes/gameboy-tc.micro
Normal file
23
runtime/colorschemes/gameboy-tc.micro
Normal file
@@ -0,0 +1,23 @@
|
||||
#Gameboy theme
|
||||
color-link default "#3f3f3f,#bfc180"
|
||||
color-link comment "#7d7343"
|
||||
color-link constant "#7d7343"
|
||||
color-link identifier "#ddde7d"
|
||||
color-link preproc "#ddde7d,#7d7343"
|
||||
color-link special "#7d7343"
|
||||
color-link statement "#7d7343"
|
||||
color-link symbol "#7d7343"
|
||||
color-link type "#7d7343"
|
||||
color-link error "#ddde7d,#7d7343"
|
||||
color-link todo "#7d7343,#ddde7d"
|
||||
color-link statusline "#ddde7d,#7d7343"
|
||||
color-link tabbar "#ddde7d,#7d7343"
|
||||
color-link color-column "#7d7343"
|
||||
color-link line-number "#ddde7d,#7d7343"
|
||||
color-link current-line-number "#3f3f3f,#bfc180"
|
||||
color-link gutter-error "#ddde7d,#7d7343"
|
||||
color-link gutter-warning "default"
|
||||
#3f3f3f
|
||||
#7d7343
|
||||
#bfc180
|
||||
#ddde76
|
||||
21
runtime/colorschemes/geany-alt-tc.micro
Normal file
21
runtime/colorschemes/geany-alt-tc.micro
Normal file
@@ -0,0 +1,21 @@
|
||||
#Geany Alternate theme
|
||||
color-link default "#000000,#fefefe"
|
||||
color-link comment "#808080"
|
||||
color-link constant "default"
|
||||
color-link constant.bool "#003030"
|
||||
color-link constant.number "#300008"
|
||||
color-link constant.string "#008000"
|
||||
color-link identifier "default"
|
||||
color-link preproc "#bbbb77"
|
||||
color-link special "#003030"
|
||||
color-link statement "#003030"
|
||||
color-link symbol "#300008"
|
||||
color-link symbol.tag "bold #4e9d71"
|
||||
color-link type "#003030"
|
||||
color-link error "#a52a2a"
|
||||
color-link todo "#ffa500"
|
||||
color-link line-number "#000000,#d0d0d0"
|
||||
color-link current-line-number "#000000,#d0d0d0"
|
||||
color-link color-column "#c2ebc2"
|
||||
color-link cursor-line "#f0f0f0"
|
||||
color-link type.extended "default"
|
||||
23
runtime/colorschemes/geany.micro
Normal file
23
runtime/colorschemes/geany.micro
Normal file
@@ -0,0 +1,23 @@
|
||||
#Geany
|
||||
color-link comment "red"
|
||||
color-link constant "default"
|
||||
color-link constant.number
|
||||
color-link constant.string "bold yellow"
|
||||
color-link identifier "default"
|
||||
color-link preproc "cyan"
|
||||
color-link special "blue"
|
||||
color-link statement "blue"
|
||||
color-link symbol "default"
|
||||
color-link symbol.tag "bold blue"
|
||||
color-link type "blue"
|
||||
color-link type.extended "default"
|
||||
color-link error "red"
|
||||
color-link todo "bold cyan"
|
||||
color-link indent-char "bold black"
|
||||
color-link line-number ""
|
||||
color-link current-line-number ""
|
||||
color-link statusline "black,white"
|
||||
color-link tabbar "black,white"
|
||||
color-link color-column "bold geren"
|
||||
color-link gutter-error ",red"
|
||||
color-link gutter-warning "red"
|
||||
24
runtime/colorschemes/github-tc.micro
Normal file
24
runtime/colorschemes/github-tc.micro
Normal file
@@ -0,0 +1,24 @@
|
||||
#True color theme based on Github's syntax highlighting.
|
||||
#Warning, this is based on how it rendered in my Firefox!
|
||||
#Yours may look different.
|
||||
color-link comment "bold #969896"
|
||||
color-link constant "#0086B9"
|
||||
color-link constant.number "#0086B9"
|
||||
color-link constant.specialChar "bold #1836BD"
|
||||
color-link constant.string "bold #1836BD"
|
||||
color-link constant.bool "#0086B9"
|
||||
color-link identifier "#A71D5D"
|
||||
color-link preproc "bold #A71D5D"
|
||||
color-link special "#A71D5D"
|
||||
color-link statement "#A71D5D"
|
||||
color-link symbol "default"
|
||||
color-link type "#A71D5D"
|
||||
color-link error "bold ,#E34234"
|
||||
color-link todo "white"
|
||||
color-link indent-char "default"
|
||||
color-link line-number "bold #969896"
|
||||
color-link current-line-number "bold #969896"
|
||||
color-link gutter-error "bold ,#E34234"
|
||||
color-link gutter-warning "bold #f26522"
|
||||
color-link statusline "bold #c8c9cb,#24292e"
|
||||
color-link tabbar "bold #c8c9cb,#24292e"
|
||||
24
runtime/colorschemes/github.micro
Normal file
24
runtime/colorschemes/github.micro
Normal file
@@ -0,0 +1,24 @@
|
||||
#Theme based on Github's syntax highlighting.
|
||||
color-link comment "bold black"
|
||||
color-link constant "cyan"
|
||||
color-link constant.number "cyan"
|
||||
color-link constant.specialChar "bold blue"
|
||||
color-link constant.string "bold blue"
|
||||
color-link constant.bool "cyan"
|
||||
color-link identifier "magenta"
|
||||
color-link preproc "bold magenta"
|
||||
color-link special "magenta"
|
||||
color-link statement "magenta"
|
||||
color-link symbol "default"
|
||||
color-link type "magenta"
|
||||
color-link error "bold ,brightred"
|
||||
color-link todo "white"
|
||||
color-link indent-char "default"
|
||||
color-link line-number "bold black"
|
||||
color-link current-line-number "bold black"
|
||||
color-link gutter-error ",red"
|
||||
color-link gutter-warning "bold yellow"
|
||||
color-link statusline "bold white,black"
|
||||
color-link tabbar "bold white,black"
|
||||
#Plain brackets.
|
||||
#color-link symbol.brackets "default"
|
||||
@@ -17,3 +17,5 @@ color-link line-number "#665c54,#282828"
|
||||
color-link current-line-number "#665c54,#3c3836"
|
||||
color-link cursor-line "#3c3836"
|
||||
color-link color-column "#79740e"
|
||||
color-link statusline "#ebdbb2,#665c54"
|
||||
color-link tabbar "#ebdbb2,#665c54"
|
||||
|
||||
@@ -15,3 +15,5 @@ color-link line-number "243,237"
|
||||
color-link current-line-number "172,237"
|
||||
color-link cursor-line "237"
|
||||
color-link color-column "237"
|
||||
color-link statusline "223,237"
|
||||
color-link tabbar "223,237"
|
||||
25
runtime/colorschemes/mc.micro
Normal file
25
runtime/colorschemes/mc.micro
Normal file
@@ -0,0 +1,25 @@
|
||||
#Midnight Commander inspired theme.
|
||||
color-link default "white,blue"
|
||||
color-link comment "bold black"
|
||||
color-link constant "bold white"
|
||||
color-link constant.string "bold yellow"
|
||||
color-link identifier "bold red"
|
||||
color-link statement "bold cyan"
|
||||
color-link symbol "white"
|
||||
color-link symbol.brackets "white"
|
||||
color-link symbol.tag "bold green"
|
||||
color-link preproc "black,cyan"
|
||||
color-link type "green"
|
||||
color-link special "magenta"
|
||||
color-link ignore "default"
|
||||
color-link error ",brightred"
|
||||
color-link todo ",brightyellow"
|
||||
color-link indent-char ",cyan"
|
||||
color-link line-number "green"
|
||||
color-link statusline "black,cyan"
|
||||
color-link tabbar "black,cyan"
|
||||
color-link current-line-number "black,cyan"
|
||||
color-link cursor-line "black,cyan"
|
||||
color-link gutter-error ",red"
|
||||
color-link gutter-warning "red"
|
||||
color-link color-column "cyan"
|
||||
5
runtime/colorschemes/monochrome-paper.micro
Normal file
5
runtime/colorschemes/monochrome-paper.micro
Normal file
@@ -0,0 +1,5 @@
|
||||
#Monochrome Paper theme.
|
||||
#Edit your files on a white background without colors.
|
||||
color-link default "black,white"
|
||||
color-link statusline "white,black"
|
||||
color-link tabbar "white,black"
|
||||
3
runtime/colorschemes/monochrome.micro
Normal file
3
runtime/colorschemes/monochrome.micro
Normal file
@@ -0,0 +1,3 @@
|
||||
#Monochrome
|
||||
#This makes micro use only the terminal's default
|
||||
# foreground and background colours.
|
||||
@@ -13,6 +13,7 @@ color-link underlined "#D33682,#282828"
|
||||
color-link error "bold #CB4B16,#282828"
|
||||
color-link todo "bold #D33682,#282828"
|
||||
color-link statusline "#282828,#F8F8F2"
|
||||
color-link tabbar "#282828,#F8F8F2"
|
||||
color-link indent-char "#505050,#282828"
|
||||
color-link line-number "#AAAAAA,#323232"
|
||||
color-link current-line-number "#AAAAAA,#282828"
|
||||
@@ -20,3 +21,7 @@ color-link gutter-error "#CB4B16,#282828"
|
||||
color-link gutter-warning "#E6DB74,#282828"
|
||||
color-link cursor-line "#323232"
|
||||
color-link color-column "#323232"
|
||||
#No extended types; Plain brackets.
|
||||
color-link type.extended "default"
|
||||
#color-link symbol.brackets "default"
|
||||
color-link symbol.tag "#AE81FF,#282828"
|
||||
|
||||
30
runtime/colorschemes/nano.micro
Normal file
30
runtime/colorschemes/nano.micro
Normal file
@@ -0,0 +1,30 @@
|
||||
#Colorscheme styled after default Debian nano.
|
||||
color-link comment "bold blue"
|
||||
color-link comment.bright "cyan"
|
||||
color-link constant "red"
|
||||
color-link constant.bool "yellow"
|
||||
color-link constant.bool.true "bold green"
|
||||
color-link constant.bool.false "bold red"
|
||||
color-link constant.number "default"
|
||||
color-link constant.specialChar "bold magenta"
|
||||
color-link constant.string "bold yellow"
|
||||
color-link identifier "bold blue"
|
||||
color-link identifier.macro "bold red"
|
||||
color-link statement "bold green"
|
||||
color-link symbol "green"
|
||||
#color-link symbol.tag "blue"
|
||||
color-link preproc "brightcyan"
|
||||
color-link type "green"
|
||||
color-link special "magenta"
|
||||
color-link ignore "default"
|
||||
color-link error "white,black"
|
||||
color-link todo "bold cyan"
|
||||
color-link indent-char ",green"
|
||||
color-link line-number "default"
|
||||
color-link current-line-number "default"
|
||||
color-link gutter-error ",white"
|
||||
color-link gutter-warning "white"
|
||||
color-link cursor-line "default"
|
||||
color-link color-column "white"
|
||||
#No extended types ( bool in C ); Plain brackets
|
||||
color-link type.extended "default"
|
||||
30
runtime/colorschemes/nes-tc.micro
Normal file
30
runtime/colorschemes/nes-tc.micro
Normal file
@@ -0,0 +1,30 @@
|
||||
#NES
|
||||
#A color theme only using NES pallette colours
|
||||
color-link default ""
|
||||
color-link comment ""
|
||||
color-link constant ""
|
||||
color-link constant.bool ""
|
||||
color-link constant.bool.true ""
|
||||
color-link constant.bool.false ""
|
||||
color-link constant.number ""
|
||||
color-link constant.specialChar ""
|
||||
color-link constant.string ""
|
||||
color-link constant.string.url "underline"
|
||||
color-link identifier ""
|
||||
color-link identifier.var ""
|
||||
color-link preproc ""
|
||||
color-link special ""
|
||||
color-link statement ""
|
||||
color-link symbol ""
|
||||
color-link symbol.brackets ""
|
||||
color-link symbol.tag ""
|
||||
color-link type ""
|
||||
color-link type.keyword ""
|
||||
color-link error ""
|
||||
color-link todo ""
|
||||
color-link cursor-line ""
|
||||
color-link statusline ""
|
||||
color-link tabbar ""
|
||||
color-link color-column ""
|
||||
color-link gutter-error ""
|
||||
color-link gutter-warning ""
|
||||
22
runtime/colorschemes/paper-tc.micro
Normal file
22
runtime/colorschemes/paper-tc.micro
Normal file
@@ -0,0 +1,22 @@
|
||||
#Paper theme, true color edition
|
||||
#Edit on an *actual* white background!
|
||||
color-link default "#000000,#efefef"
|
||||
color-link comment ""
|
||||
color-link constant ""
|
||||
color-link constant.string ""
|
||||
color-link constant.string.url "underline #0000dd"
|
||||
color-link identifier ""
|
||||
color-link identifier.var ""
|
||||
color-link special ""
|
||||
color-link statement ""
|
||||
color-link symbol ""
|
||||
color-link symbol.brackets ""
|
||||
color-link symbol.tag ""
|
||||
color-link type ""
|
||||
color-link statusline ""
|
||||
color-link tabbar ""
|
||||
color-link error ""
|
||||
color-link todo ""
|
||||
color-link color-column ""
|
||||
color-link gutter-error ""
|
||||
color-link gutter-warning ""
|
||||
27
runtime/colorschemes/paper.micro
Normal file
27
runtime/colorschemes/paper.micro
Normal file
@@ -0,0 +1,27 @@
|
||||
#Paper theme, Edit on a white background.
|
||||
color-link default "black,white"
|
||||
color-link comment "bold black"
|
||||
color-link constant "cyan"
|
||||
color-link constant.string "bold green"
|
||||
color-link identifier "blue"
|
||||
color-link identifier.macro "bold red"
|
||||
color-link identifier.var "bold blue"
|
||||
color-link identifier.class "bold green"
|
||||
color-link statement "green"
|
||||
color-link symbol "red"
|
||||
color-link symbol.brackets "default"
|
||||
color-link symbol.tag "bold blue"
|
||||
color-link preproc "bold cyan"
|
||||
color-link type "green"
|
||||
color-link special "magenta"
|
||||
color-link ignore "default"
|
||||
color-link error ",brightred"
|
||||
color-link todo ",brightyellow"
|
||||
color-link indent-char ",brightgreen"
|
||||
color-link line-number "black"
|
||||
color-link statusline "white,black"
|
||||
color-link tabbar "white,black"
|
||||
color-link current-line-number "blue"
|
||||
color-link gutter-error ",red"
|
||||
color-link gutter-warning "red"
|
||||
color-link color-column "black"
|
||||
@@ -14,5 +14,12 @@ color-link line-number "yellow"
|
||||
color-link current-line-number "red"
|
||||
color-link gutter-error ",red"
|
||||
color-link gutter-warning "red"
|
||||
color-link cursor-line "white"
|
||||
#Cursor line causes readability issues. Disabled for now.
|
||||
#color-link cursor-line "white,black"
|
||||
color-link color-column "white"
|
||||
#No extended types. (bool in C)
|
||||
color-link type.extended "default"
|
||||
#No bracket highlighting.
|
||||
color-link symbol.brackets "default"
|
||||
#Color shebangs the comment color
|
||||
color-link preproc.shebang "comment"
|
||||
|
||||
@@ -11,6 +11,7 @@ color-link underlined "#D33682,#002833"
|
||||
color-link error "bold #CB4B16,#002833"
|
||||
color-link todo "bold #D33682,#002833"
|
||||
color-link statusline "#003541,#839496"
|
||||
color-link tabbar "#003541,#839496"
|
||||
color-link indent-char "#586E75,#002833"
|
||||
color-link line-number "#586E75,#003541"
|
||||
color-link current-line-number "#586E75,#002833"
|
||||
@@ -18,3 +19,5 @@ color-link gutter-error "#003541,#CB4B16"
|
||||
color-link gutter-warning "#CB4B16,#002833"
|
||||
color-link cursor-line "#003541"
|
||||
color-link color-column "#003541"
|
||||
color-link type.extended "default"
|
||||
color-link symbol.brackets "default"
|
||||
@@ -1,19 +1,23 @@
|
||||
color-link comment "brightgreen"
|
||||
color-link comment "bold brightgreen"
|
||||
color-link constant "cyan"
|
||||
color-link constant.specialChar "red"
|
||||
color-link identifier "blue"
|
||||
color-link statement "green"
|
||||
color-link symbol "green"
|
||||
color-link preproc "brightred"
|
||||
color-link type "yellow"
|
||||
color-link special "red"
|
||||
color-link special "blue"
|
||||
color-link underlined "magenta"
|
||||
color-link error "bold brightred"
|
||||
color-link todo "bold magenta"
|
||||
color-link statusline "black,brightblue"
|
||||
color-link tabbar "black,brightblue"
|
||||
color-link indent-char "black"
|
||||
color-link line-number "brightgreen,black"
|
||||
color-link current-line-number "brightgreen,default"
|
||||
color-link line-number "bold brightgreen,black"
|
||||
color-link current-line-number "bold brightgreen,default"
|
||||
color-link gutter-error "black,brightred"
|
||||
color-link gutter-warning "brightred,default"
|
||||
color-link cursor-line "black"
|
||||
color-link color-column "black"
|
||||
color-link type.extended "default"
|
||||
color-link symbol.brackets "default"
|
||||
|
||||
23
runtime/colorschemes/symbian-tc.micro
Normal file
23
runtime/colorschemes/symbian-tc.micro
Normal file
@@ -0,0 +1,23 @@
|
||||
#Symbian
|
||||
color-link default "#000000,#ff8a00"
|
||||
color-link comment "#8c0000"
|
||||
color-link constant "#8c0000"
|
||||
color-link identifier "#ffff8c"
|
||||
color-link preproc "#ffff8c,#8c0000"
|
||||
color-link special "#8c0000"
|
||||
color-link statement "#8c0000"
|
||||
color-link symbol "#8c0000"
|
||||
color-link type "#8c0000"
|
||||
color-link error "#ffff8c,#8c0000"
|
||||
color-link todo "#8c0000,#ffff8c"
|
||||
color-link statusline "#ffff8c,#8c0000"
|
||||
color-link tabbar "#ffff8c,#8c0000"
|
||||
color-link color-column "#8c0000"
|
||||
color-link line-number "#ffff8c,#8c0000"
|
||||
color-link current-line-number "#000000,#ff8a00"
|
||||
color-link gutter-error "#ffff8c,#8c0000"
|
||||
color-link gutter-warning "default"
|
||||
#000000
|
||||
#8c0000
|
||||
#ff8a00
|
||||
#ffff8c
|
||||
@@ -13,6 +13,7 @@ color-link underlined "188,237"
|
||||
color-link error "115,236"
|
||||
color-link todo "bold 254,237"
|
||||
color-link statusline "186,236"
|
||||
color-link tabbar "186,236"
|
||||
color-link indent-char "238,237"
|
||||
color-link line-number "248,238"
|
||||
color-link gutter-error "237,174"
|
||||
|
||||
@@ -5,13 +5,18 @@ This help page aims to cover two aspects of micro's syntax highlighting engine:
|
||||
- How to create colorschemes and use them
|
||||
- How to create syntax files to add to the list of languages micro can highlight
|
||||
|
||||
### Colorschemes
|
||||
## Colorschemes
|
||||
|
||||
Micro comes with a number of colorschemes by default. Here is the list:
|
||||
|
||||
* simple: this is the simplest colorscheme. It uses 16 colors which are
|
||||
set by your terminal
|
||||
|
||||
* mc: A 16-color theme based on the look and feel of GNU Midnight Commander.
|
||||
This will look great used in conjunction with Midnight Commander.
|
||||
|
||||
* nano: A 16-color theme loosely based on GNU nano's syntax highlighting.
|
||||
|
||||
* monokai: this is the monokai colorscheme; you may recognize it as
|
||||
Sublime Text's default colorscheme. It requires true color to
|
||||
look perfect, but the 256 color approximation looks very good as well.
|
||||
@@ -29,15 +34,47 @@ Micro comes with a number of colorschemes by default. Here is the list:
|
||||
* atom-dark-tc: this colorscheme is based off of Atom's "dark" colorscheme.
|
||||
It requires true color to look good.
|
||||
|
||||
* cmc-16: A very nice 16-color theme. Written by contributor CaptainMcClellan
|
||||
(Collin Warren.) Licensed under the same license as the rest of the themes.
|
||||
|
||||
* cmc-paper: Basically cmc-16, but on a white background. ( Actually light grey on most
|
||||
ANSI (16-color) terminals.)
|
||||
|
||||
* cmc-tc: A true colour variant of the cmc theme.
|
||||
It requires true color to look its best. Use cmc-16 if your terminal doesn't support true color.
|
||||
|
||||
* codeblocks: A colorscheme based on the Code::Blocks IDE's default syntax highlighting.
|
||||
|
||||
* codeblocks-paper: Same as codeblocks, but on a white background. ( Actually light grey. )
|
||||
|
||||
* github-tc: A colorscheme based on Github's syntax highlighting. Requires true color to look its best.
|
||||
|
||||
* paper-tc: A nice minimalist theme with a light background, good for editing documents on.
|
||||
Requires true color to look its best. Not to be confused with `-paper` suffixed themes.
|
||||
|
||||
* geany: Colorscheme based on geany's default highlighting.
|
||||
|
||||
* geany-alt-tc: Based on an alternate theme bundled with geany.
|
||||
|
||||
* flamepoint-tc: A fire inspired, high intensity true color theme written by CaptainMcClellan.
|
||||
As with all the other `-tc` suffixed themes, it looks its best on a
|
||||
|
||||
To enable one of these colorschemes just press CtrlE in micro and type `set colorscheme solarized`.
|
||||
(or whichever one you choose).
|
||||
(or whichever one you choose). You can also use `set colorscheme monochrome` if you'd prefer
|
||||
to have just the terminal's default foreground and background colors.
|
||||
Note: This provides no syntax highlighting!
|
||||
|
||||
See `help gimmickcolors` for a list of some true colour themes that are more
|
||||
just for fun than for serious use. ( Though feel free if you want! )
|
||||
|
||||
---
|
||||
|
||||
### Creating a Colorscheme
|
||||
|
||||
Micro's colorschemes are also extremely simple to create. The default ones can be found
|
||||
[here](https://github.com/zyedidia/micro/tree/master/runtime/colorschemes).
|
||||
|
||||
They are only about 18 lines in total.
|
||||
They are only about 18-30 lines in total.
|
||||
|
||||
Basically to create the colorscheme you need to link highlight groups with actual colors.
|
||||
This is done using the `color-link` command.
|
||||
@@ -84,7 +121,8 @@ If the user's terminal supports true color, then you can also specify colors exa
|
||||
their hex codes. If the terminal is not true color but micro is told to use a true color colorscheme
|
||||
it will attempt to map the colors to the available 256 colors.
|
||||
|
||||
Generally colorschemes which require true color terminals to look good are marked with a `-tc` suffix.
|
||||
Generally colorschemes which require true color terminals to look good are marked with a `-tc` suffix
|
||||
and colorschemes which supply a white background are marked with a `-paper` suffix.
|
||||
|
||||
---
|
||||
|
||||
@@ -102,57 +140,165 @@ Here is a list of the colorscheme groups that you can use:
|
||||
* underlined
|
||||
* error
|
||||
* todo
|
||||
* statusline (color of the statusline)
|
||||
* indent-char (color of the character which indicates tabs if the option is enabled)
|
||||
* statusline ( Color of the statusline)
|
||||
* tabbar ( Color of the tabbar that lists open files.)
|
||||
* indent-char ( Color of the character which indicates tabs if the option is enabled)
|
||||
* line-number
|
||||
* gutter-error
|
||||
* gutter-warning
|
||||
* cursor-line
|
||||
* current-line-number
|
||||
* color-column
|
||||
* ignore
|
||||
* divider ( Color of the divider between vertical splits. )
|
||||
|
||||
Colorschemes can be placed in the `~/.config/micro/colorschemes` directory to be used.
|
||||
|
||||
### Syntax files
|
||||
|
||||
The syntax files specify how to highlight certain languages.
|
||||
|
||||
The first statement in a syntax file will probably the syntax statement. This tells micro
|
||||
what language the syntax file is for and how to detect a file in that language.
|
||||
|
||||
Essentially, it's just
|
||||
|
||||
```
|
||||
syntax "Name of language" "\.extension$"
|
||||
```
|
||||
|
||||
For the extension, micro will just compare that regex to the filename and if it matches then it
|
||||
will use the syntax rules defined in the remainder of the file.
|
||||
|
||||
There is also a possibility to use a header statement which is a regex that micro will compare
|
||||
with the first line of the file. This is almost only used for shebangs at the top of shell scripts
|
||||
which don't have any extension (see sh.micro for an example).
|
||||
Colorschemes must be placed in the `~/.config/micro/colorschemes` directory to be used.
|
||||
|
||||
---
|
||||
|
||||
The rest of a syntax file is very simple and is essentially a list of regexes specifying how to highlight
|
||||
different expressions.
|
||||
In addition to the main colorscheme groups, there are subgroups that you can
|
||||
specify by adding `.subgroup` to the group. If you're creating your own
|
||||
custom syntax files, you can make use of your own subgroups.
|
||||
|
||||
It is recommended that when creating a syntax file you use the colorscheme groups (see above) to
|
||||
highlight different expressions. You may also hard code colors, but that may not look good depending
|
||||
on what terminal colorscheme the user has installed.
|
||||
If micro can't match the subgroup, it'll default to the root group, so
|
||||
it's safe and recommended to use subgroups in your custom syntax files.
|
||||
|
||||
Here is an example to highlight comments (expressions starting with `//`):
|
||||
For example if `constant.string` is found in your colorscheme, micro will
|
||||
use that for highlighting strings. If it's not found, it will use constant
|
||||
instead. Micro tries to match the largest set of groups it can find in the
|
||||
colorscheme definitions, so if, for examle `constant.bool.true` is found then
|
||||
micro will use that. If `constant.bool.true` is not found but `constant.bool`
|
||||
is found micro will use `constant.bool`. If not, it uses `constant`.
|
||||
|
||||
Here's a list of subgroups used in micro's built-in syntax files.
|
||||
|
||||
* comment.bright ( Some filetypes have distinctions between types of comments.)
|
||||
* constant.bool
|
||||
* constant.bool.true
|
||||
* constant.bool.false
|
||||
* constant.number
|
||||
* constant.specialChar
|
||||
* constant.string
|
||||
* constant.string.url
|
||||
* identifier.class ( Also used for functions. )
|
||||
* identifier.macro
|
||||
* identifier.var
|
||||
* preproc.shebang ( The #! at the beginning of a file that tells the os what script interpreter to use. )
|
||||
* symbol.brackets ( {}()[] and sometimes <> )
|
||||
* symbol.operator ( Color operator symbols differently. )
|
||||
* symbol.tag ( For html tags, among other things.)
|
||||
* type.keyword ( If you want a special highlight for keywords like `private` )
|
||||
|
||||
In the future, plugins may also be able to use color groups for styling.
|
||||
|
||||
## Syntax files
|
||||
|
||||
The syntax files is written in yaml-format and specify how to highlight languages.
|
||||
|
||||
Micro's builtin syntax highlighting tries very hard to be sane, sensible
|
||||
and provide ample coverage of the meaningful elements of a language. Micro has
|
||||
syntax files built int for over 100 languages now. However, there may be
|
||||
situations where you find Micro's highlighting to be insufficient or not to
|
||||
your liking. Good news is you can create syntax files (.micro extension), place them in
|
||||
`~/.config/micro/syntax` and Micro will use those instead.
|
||||
|
||||
### Filetype defintion
|
||||
|
||||
You must start the syntax file by declaring the filetype:
|
||||
|
||||
```
|
||||
color comment "//.*"
|
||||
filetype: go
|
||||
```
|
||||
|
||||
This will highlight the regex `//.*` in the color that the user's colorscheme has linked to the comment
|
||||
group.
|
||||
#### Detect definition
|
||||
|
||||
Note that this regex only matches the current line. Here is an example for multiline comments (`/* comment */`):
|
||||
Then you must provide information about how to detect the filetype:
|
||||
|
||||
```
|
||||
color comment start="/\*" end="\*/"
|
||||
detect:
|
||||
filename: "\\.go$"
|
||||
```
|
||||
|
||||
Micro will match this regex against a given filename to detect the filetype. You may also
|
||||
provide an optional `header` regex that will check the first line of the file. For example:
|
||||
|
||||
```
|
||||
detect:
|
||||
filename: "\\.ya?ml$"
|
||||
header: "%YAML"
|
||||
```
|
||||
|
||||
#### Syntax rules
|
||||
|
||||
Next you must provide the syntax highlighting rules. There are two types of rules: patterns and regions.
|
||||
A pattern is matched on a single line and usually a single word as well. A region highlights between two
|
||||
patterns over multiple lines and may have rules of its own inside the region.
|
||||
|
||||
Here are some example patterns in Go:
|
||||
|
||||
```
|
||||
rules:
|
||||
- special: "\\b(break|case|continue|default|go|goto|range|return)\\b"
|
||||
- statement: "\\b(else|for|if|switch)\\b"
|
||||
- preproc: "\\b(package|import|const|var|type|struct|func|go|defer|iota)\\b"
|
||||
```
|
||||
|
||||
The order of patterns does matter as patterns lower in the file will overwrite the ones defined above them.
|
||||
|
||||
And here are some example regions for Go:
|
||||
|
||||
```
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
rules:
|
||||
- constant.specialChar: "%."
|
||||
- constant.specialChar: "\\\\[abfnrtv'\\\"\\\\]"
|
||||
- constant.specialChar: "\\\\([0-7]{3}|x[A-Fa-f0-9]{2}|u[A-Fa-f0-9]{4}|U[A-Fa-f0-9]{8})"
|
||||
|
||||
- comment:
|
||||
start: "//"
|
||||
end: "$"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
|
||||
- comment:
|
||||
start: "/\\*"
|
||||
end: "\\*/"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
```
|
||||
|
||||
Notice how the regions may contain rules inside of them. Any inner rules that are matched are then skipped when searching
|
||||
for the end of the region. For example, when highlighting `"foo \" bar"`, since `\"` is matched by an inner rule in the
|
||||
region, it is skipped. Likewise for `"foo \\" bar`, since `\\` is matched by an inner rule, it is skipped, and then the `"`
|
||||
is found and the string ends at the correct place.
|
||||
|
||||
You may also explicitly mark skip regexes if you don't want them to be highlighted. For example:
|
||||
|
||||
```
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\."
|
||||
rules: []
|
||||
```
|
||||
|
||||
#### Includes
|
||||
|
||||
You may also include rules from other syntax files as embedded languages. For example, the following is possible
|
||||
for html:
|
||||
|
||||
```
|
||||
- default:
|
||||
start: "<script.*?>"
|
||||
end: "</script.*?>"
|
||||
rules:
|
||||
- include: "javascript"
|
||||
|
||||
- default:
|
||||
start: "<style.*?>"
|
||||
end: "</style.*?>"
|
||||
rules:
|
||||
- include: "css"
|
||||
```
|
||||
|
||||
@@ -42,6 +42,10 @@ Here are the possible commands that you can use.
|
||||
|
||||
* `tab filename`: opens the given file in a new tab.
|
||||
|
||||
* `tabswitch tab`: This command will switch to the specified tab.
|
||||
The `tab` can either be a tab number, or a name of a tab.
|
||||
|
||||
|
||||
* `log`: opens a log of all messages and debug statements.
|
||||
|
||||
* `plugin install plugin_name`: installs the given plugin.
|
||||
|
||||
141
runtime/help/defaultkeys.md
Normal file
141
runtime/help/defaultkeys.md
Normal file
@@ -0,0 +1,141 @@
|
||||
#Default Keys
|
||||
|
||||
Below are simple charts of the default hotkeys and their functions.
|
||||
For more information about binding custom hotkeys or changing
|
||||
default bindings, please run `>help keybindings`
|
||||
|
||||
Please remember that *all* keys here are rebindable!
|
||||
If you don't like it, you can change it!
|
||||
|
||||
(We are not responsible for you forgetting what you bind keys to.
|
||||
Do not open an issue because you forgot your keybindings.)
|
||||
|
||||
#Power user
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+E | Switch to the micro command prompt to run a command. |
|
||||
| | (See `>help commands` for a list of commands. ) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+B | Run shell commands in micro's current working directory.|
|
||||
+--------+---------------------------------------------------------+
|
||||
|
||||
#Navigation
|
||||
|
||||
+--------+---------------------------------------------------------+
|
||||
| Key | Description of function |
|
||||
|--------+---------------------------------------------------------+
|
||||
| Arrows | Move the cursor around your current document. |
|
||||
| | (Yes this is rebindable to the vim keys if you want.) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Shift+ | Move and select text. |
|
||||
| Arrows | |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Home | Move to the beginning of the current line. (Naturally.) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| End | Move to the end of the current line. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| PageUp | Move cursor up lines quickly. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| PageDn | Move cursor down lines quickly. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+L | Jump to line in current file. ( Prompts for line # ) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+W | Move between splits open in current tab. |
|
||||
| | (See vsplit and hsplit in `>help commands`) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+T | Open a new tab. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Alt+, | Move to the previous tab in the tablist. |
|
||||
| | (This works like moving between file buffers in nano) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Alt+. | Move to the next tab in the tablist. |
|
||||
+--------+---------------------------------------------------------+
|
||||
|
||||
#Find Operations
|
||||
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+F | Find text in current file. ( Prompts for text to find.) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+N | Find next instance of current search in current file. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+P | Find prev instance of current search in current file. |
|
||||
+--------+---------------------------------------------------------+
|
||||
|
||||
#File Operations
|
||||
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+Q | Close current file. ( Quits micro if last file open. ) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+O | Open a file. ( Prompts you to input filename. ) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+S | Save current file. |
|
||||
+--------+---------------------------------------------------------+
|
||||
|
||||
#Text operations
|
||||
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+A | Select all text in current file. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+X | Cut selected text. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+C | Copy selected text. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+V | Paste selected text. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+K | Cut current line. ( Can then be pasted with Ctrl+V) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+D | Duplicate current line. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+Z | Undo actions. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+Y | Redo actions. |
|
||||
+--------+---------------------------------------------------------+
|
||||
|
||||
#Other
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+G | Open the help file. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+H | Alternate backspace. |
|
||||
| | (Some old terminals don't support the Backspace key .) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Ctrl+R | Toggle the line number ruler. ( On the lefthand side.) |
|
||||
+--------+---------------------------------------------------------+
|
||||
|
||||
#Emacs style actions
|
||||
|
||||
+--------+---------------------------------------------------------+
|
||||
| Alt+F | Move to the end of the next word. (To the next space.) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Alt+B | Move to the beginning of the previous word. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Alt+A | Alternate Home key. ( Move to beginning of line. ) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Alt+E | Alternate End key. ( Move to the end of line.) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Alt+P | Move cursor up. ( Same as up key. ) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| Alt+N | Move cursor down. ( Same as down key. ) |
|
||||
+--------+---------------------------------------------------------+
|
||||
|
||||
#Function keys.
|
||||
|
||||
Warning! The function keys may not work in all terminals!
|
||||
+--------+---------------------------------------------------------+
|
||||
| F1 | Open help. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| F2 | Save current file. |
|
||||
+--------+---------------------------------------------------------+
|
||||
| F3 | Find in current file. ( Same as Ctrl+F ) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| F4 | Close current file. (Quit if only file.) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| F7 | Find in current file. (Same as Ctrl+F) |
|
||||
+--------+---------------------------------------------------------+
|
||||
| F10 | Close current file. |
|
||||
+--------+---------------------------------------------------------+
|
||||
|
||||
#Macros
|
||||
|
||||
Micro supports the use of keyboard macros. Simply press Ctrl+U to
|
||||
begin recording a macro and press Ctrl+U to stop recording.
|
||||
|
||||
Press Ctrl+J to run your recorded macro.
|
||||
14
runtime/help/gimmickcolors.md
Normal file
14
runtime/help/gimmickcolors.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Gimmick colors
|
||||
|
||||
We have included a few colorschemes that are for fun:
|
||||
|
||||
* funky-cactus: I don't know why I made this. (Written by CaptainMcClellan)
|
||||
* gameboy-tc: Colorscheme based on the olive green original Gameboy!
|
||||
* nes-tc: A colorscheme and syntax highlighting using only colors in the
|
||||
Nintendo Entertainment System color palette.
|
||||
* symbian-tc: Colorscheme based on SymbOS's GUI.
|
||||
* matrix: Pretend it's 1981 with a colorscheme based on a monochrome
|
||||
IBM 5151. ( Does not include the ghosting and trailing. )
|
||||
|
||||
Check the plugin repo periodically for gimmick-color extension packs
|
||||
and genuine additional themes.
|
||||
@@ -1,5 +1,6 @@
|
||||
# Micro help text
|
||||
|
||||
Thank you for downloading and using micro.
|
||||
Micro is a terminal-based text editor that aims to be easy to use and intuitive,
|
||||
while also taking advantage of the full capabilities of modern terminals.
|
||||
|
||||
@@ -12,9 +13,11 @@ See the next section for more information about documentation and help.
|
||||
Press CtrlQ to quit, and CtrlS to save. Press CtrlE to start typing commands
|
||||
and you can see which commands are available by pressing tab, or by
|
||||
viewing the help topic `> help commands`. When I write `> ...` I mean press
|
||||
CtrlE and then type whatever is there.
|
||||
CtrlE and then type whatever is there.
|
||||
|
||||
Move the cursor around with the mouse or the arrow keys.
|
||||
Move the cursor around with the mouse or the arrow keys. Type `>help defaultkeys` to
|
||||
get a quick, easy overview of the default hotkeys and what they do. For more info
|
||||
on rebinding keys, see type `>help keybindings`
|
||||
|
||||
If the colorscheme doesn't look good, you can change it with `> set colorscheme ...`.
|
||||
You can press tab to see the available colorschemes, or see more information with
|
||||
@@ -34,6 +37,7 @@ Here are the possible help topics that you can read:
|
||||
|
||||
* tutorial: A brief tutorial which gives an overview of all the other help topics
|
||||
* keybindings: Gives a full list of the default keybindings as well as how to rebind them
|
||||
* defaultkeys: Gives a more straight-forward list of the hotkey commands and what they do.
|
||||
* commands: Gives a list of all the commands and what they do
|
||||
* options: Gives a list of all the options you can customize
|
||||
* plugins: Explains how micro's plugin system works and how to create your own plugins
|
||||
|
||||
@@ -1,89 +1,15 @@
|
||||
# Keybindings
|
||||
|
||||
Here are the default keybindings in json format. You can rebind them to your liking, following the same format.
|
||||
Micro has a plethora of hotkeys that make it easy and powerful to use and all
|
||||
hotkeys are fully customizable to your liking.
|
||||
Custom keybindings are stored internally in micro if changed with the `>bind` command or
|
||||
you can also be added in the file `~/.config/micro/bindings.json` as discussed below.
|
||||
For a list of the default keybindings in the json format used by micro, please see
|
||||
the end of this file. For a more user-friendly list with explanations of what the default
|
||||
hotkeys are and what they do, please see `>help defaultkeys`
|
||||
|
||||
```json
|
||||
{
|
||||
"Up": "CursorUp",
|
||||
"Down": "CursorDown",
|
||||
"Right": "CursorRight",
|
||||
"Left": "CursorLeft",
|
||||
"ShiftUp": "SelectUp",
|
||||
"ShiftDown": "SelectDown",
|
||||
"ShiftLeft": "SelectLeft",
|
||||
"ShiftRight": "SelectRight",
|
||||
"AltLeft": "WordLeft",
|
||||
"AltRight": "WordRight",
|
||||
"AltShiftRight": "SelectWordRight",
|
||||
"AltShiftLeft": "SelectWordLeft",
|
||||
"AltUp": "MoveLinesUp",
|
||||
"AltDown": "MoveLinesDown",
|
||||
"CtrlLeft": "StartOfLine",
|
||||
"CtrlRight": "EndOfLine",
|
||||
"CtrlShiftLeft": "SelectToStartOfLine",
|
||||
"CtrlShiftRight": "SelectToEndOfLine",
|
||||
"CtrlUp": "CursorStart",
|
||||
"CtrlDown": "CursorEnd",
|
||||
"CtrlShiftUp": "SelectToStart",
|
||||
"CtrlShiftDown": "SelectToEnd",
|
||||
"Enter": "InsertNewline",
|
||||
"Space": "InsertSpace",
|
||||
"CtrlH": "Backspace",
|
||||
"Backspace": "Backspace",
|
||||
"Alt-CtrlH": "DeleteWordLeft",
|
||||
"Alt-Backspace": "DeleteWordLeft",
|
||||
"Tab": "IndentSelection,InsertTab",
|
||||
"Backtab": "OutdentSelection",
|
||||
"CtrlO": "OpenFile",
|
||||
"CtrlS": "Save",
|
||||
"CtrlF": "Find",
|
||||
"CtrlN": "FindNext",
|
||||
"CtrlP": "FindPrevious",
|
||||
"CtrlZ": "Undo",
|
||||
"CtrlY": "Redo",
|
||||
"CtrlC": "Copy",
|
||||
"CtrlX": "Cut",
|
||||
"CtrlK": "CutLine",
|
||||
"CtrlD": "DuplicateLine",
|
||||
"CtrlV": "Paste",
|
||||
"CtrlA": "SelectAll",
|
||||
"CtrlT": "AddTab",
|
||||
"CtrlRightSq": "PreviousTab",
|
||||
"CtrlBackslash": "NextTab",
|
||||
"Home": "StartOfLine",
|
||||
"End": "EndOfLine",
|
||||
"CtrlHome": "CursorStart",
|
||||
"CtrlEnd": "CursorEnd",
|
||||
"PageUp": "CursorPageUp",
|
||||
"PageDown": "CursorPageDown",
|
||||
"CtrlG": "ToggleHelp",
|
||||
"CtrlR": "ToggleRuler",
|
||||
"CtrlL": "JumpLine",
|
||||
"Delete": "Delete",
|
||||
"CtrlB": "ShellMode",
|
||||
"CtrlQ": "Quit",
|
||||
"CtrlE": "CommandMode",
|
||||
"CtrlW": "NextSplit",
|
||||
"CtrlU": "ToggleMacro",
|
||||
"CtrlJ": "PlayMacro",
|
||||
|
||||
// Emacs-style keybindings
|
||||
"Alt-f": "WordRight",
|
||||
"Alt-b": "WordLeft",
|
||||
"Alt-a": "StartOfLine",
|
||||
"Alt-e": "EndOfLine",
|
||||
"Alt-p": "CursorUp",
|
||||
"Alt-n": "CursorDown",
|
||||
|
||||
// Integration with file managers
|
||||
"F1": "ToggleHelp",
|
||||
"F2": "Save",
|
||||
"F4": "Quit",
|
||||
"F7": "Find",
|
||||
"F10": "Quit",
|
||||
"Esc": "Escape",
|
||||
}
|
||||
```
|
||||
If `~/.config/micro/bindings.json` does not exist, you can simply create it.
|
||||
Micro will know what to do with it.
|
||||
|
||||
You can use the alt keys + arrows to move word by word.
|
||||
Ctrl left and right move the cursor to the start and end of the line, and
|
||||
@@ -106,6 +32,9 @@ following in the `bindings.json` file.
|
||||
}
|
||||
```
|
||||
|
||||
In addition to editing your `~/.config/micro/bindings.json`, you can run
|
||||
`>bind <keycombo> <action>` For a list of bindable actions, see below.
|
||||
|
||||
You can also chain commands when rebinding. For example, if you want Alt-s to save
|
||||
and quit you can bind it like so:
|
||||
|
||||
@@ -159,6 +88,7 @@ Delete
|
||||
Center
|
||||
InsertTab
|
||||
Save
|
||||
SaveAll
|
||||
SaveAs
|
||||
Find
|
||||
FindNext
|
||||
@@ -332,6 +262,95 @@ Escape
|
||||
Enter
|
||||
```
|
||||
|
||||
# Default keybinding configuration.
|
||||
|
||||
```json
|
||||
{
|
||||
"Up": "CursorUp",
|
||||
"Down": "CursorDown",
|
||||
"Right": "CursorRight",
|
||||
"Left": "CursorLeft",
|
||||
"ShiftUp": "SelectUp",
|
||||
"ShiftDown": "SelectDown",
|
||||
"ShiftLeft": "SelectLeft",
|
||||
"ShiftRight": "SelectRight",
|
||||
"AltLeft": "WordLeft",
|
||||
"AltRight": "WordRight",
|
||||
"AltShiftRight": "SelectWordRight",
|
||||
"AltShiftLeft": "SelectWordLeft",
|
||||
"AltUp": "MoveLinesUp",
|
||||
"AltDown": "MoveLinesDown",
|
||||
"CtrlLeft": "StartOfLine",
|
||||
"CtrlRight": "EndOfLine",
|
||||
"CtrlShiftLeft": "SelectToStartOfLine",
|
||||
"ShiftHome": "SelectToStartOfLine",
|
||||
"CtrlShiftRight": "SelectToEndOfLine",
|
||||
"ShiftEnd": "SelectToEndOfLine",
|
||||
"CtrlUp": "CursorStart",
|
||||
"CtrlDown": "CursorEnd",
|
||||
"CtrlShiftUp": "SelectToStart",
|
||||
"CtrlShiftDown": "SelectToEnd",
|
||||
"Enter": "InsertNewline",
|
||||
"Space": "InsertSpace",
|
||||
"CtrlH": "Backspace",
|
||||
"Backspace": "Backspace",
|
||||
"Alt-CtrlH": "DeleteWordLeft",
|
||||
"Alt-Backspace": "DeleteWordLeft",
|
||||
"Tab": "IndentSelection,InsertTab",
|
||||
"Backtab": "OutdentSelection",
|
||||
"CtrlO": "OpenFile",
|
||||
"CtrlS": "Save",
|
||||
"CtrlF": "Find",
|
||||
"CtrlN": "FindNext",
|
||||
"CtrlP": "FindPrevious",
|
||||
"CtrlZ": "Undo",
|
||||
"CtrlY": "Redo",
|
||||
"CtrlC": "Copy",
|
||||
"CtrlX": "Cut",
|
||||
"CtrlK": "CutLine",
|
||||
"CtrlD": "DuplicateLine",
|
||||
"CtrlV": "Paste",
|
||||
"CtrlA": "SelectAll",
|
||||
"CtrlT": "AddTab",
|
||||
"Alt,": "PreviousTab",
|
||||
"Alt.": "NextTab",
|
||||
"Home": "StartOfLine",
|
||||
"End": "EndOfLine",
|
||||
"CtrlHome": "CursorStart",
|
||||
"CtrlEnd": "CursorEnd",
|
||||
"PageUp": "CursorPageUp",
|
||||
"PageDown": "CursorPageDown",
|
||||
"CtrlG": "ToggleHelp",
|
||||
"CtrlR": "ToggleRuler",
|
||||
"CtrlL": "JumpLine",
|
||||
"Delete": "Delete",
|
||||
"CtrlB": "ShellMode",
|
||||
"CtrlQ": "Quit",
|
||||
"CtrlE": "CommandMode",
|
||||
"CtrlW": "NextSplit",
|
||||
"CtrlU": "ToggleMacro",
|
||||
"CtrlJ": "PlayMacro",
|
||||
|
||||
// Emacs-style keybindings
|
||||
"Alt-f": "WordRight",
|
||||
"Alt-b": "WordLeft",
|
||||
"Alt-a": "StartOfLine",
|
||||
"Alt-e": "EndOfLine",
|
||||
"Alt-p": "CursorUp",
|
||||
"Alt-n": "CursorDown",
|
||||
|
||||
// Integration with file managers
|
||||
"F1": "ToggleHelp",
|
||||
"F2": "Save",
|
||||
"F3": "Find",
|
||||
"F4": "Quit",
|
||||
"F7": "Find",
|
||||
"F10": "Quit",
|
||||
"Esc": "Escape",
|
||||
}
|
||||
```
|
||||
|
||||
#Final notes
|
||||
Note: On some old terminal emulators and on Windows machines, `CtrlH` should be used
|
||||
for backspace.
|
||||
|
||||
|
||||
@@ -65,6 +65,11 @@ Here are the options that you can set:
|
||||
|
||||
default value: `off`
|
||||
|
||||
* `tabmovement`: navigate spaces at the beginning of lines as if they are tabs (e.g. move over 4 spaces at once).
|
||||
This option only does anything if `tabstospaces` is on.
|
||||
|
||||
default value: `off`
|
||||
|
||||
* `autoindent`: when creating a new line use the same indentation as the
|
||||
previous line
|
||||
|
||||
@@ -140,6 +145,16 @@ Here are the options that you can set:
|
||||
|
||||
default value: `on`
|
||||
|
||||
* `keepautoindent`: when using autoindent, whitespace is added for you. This option determines if
|
||||
when you move to the next line without any insertions the whitespace that was added should be deleted.
|
||||
By default the autoindent whitespace is deleted if the line was left empty.
|
||||
|
||||
default value: `off`
|
||||
|
||||
* `termtitle`: defines whether or not your terminal's title will be set by micro when opened.
|
||||
|
||||
default value: `off`
|
||||
|
||||
---
|
||||
|
||||
Default plugin options:
|
||||
@@ -152,6 +167,12 @@ Default plugin options:
|
||||
|
||||
default value: `on`
|
||||
|
||||
* `ftoptions`: by default, micro will set some options based on the filetype. At the moment, micro will
|
||||
use tabs for makefiles and spaces for python files regardless of your settings. If you would like to
|
||||
disable this behavior turn this option off.
|
||||
|
||||
default value: `on`
|
||||
|
||||
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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
21
runtime/plugins/autoclose/utf8/LICENSE
Normal file
21
runtime/plugins/autoclose/utf8/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Stepets
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
109
runtime/plugins/autoclose/utf8/README.md
Normal file
109
runtime/plugins/autoclose/utf8/README.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# utf8.lua
|
||||
one-file pure-lua 5.1 regex library
|
||||
|
||||
This library _is_ the simple way to add utf8 support into your application.
|
||||
|
||||
Some examples from http://www.lua.org/manual/5.1/manual.html#5.4 :
|
||||
```Lua
|
||||
local utf8 = require "utf8"
|
||||
|
||||
local s = "hello world from Lua"
|
||||
for w in string.gmatch(s, "%a+") do
|
||||
print(w)
|
||||
end
|
||||
--[[
|
||||
hello
|
||||
world
|
||||
from
|
||||
Lua
|
||||
]]--
|
||||
|
||||
s = "Привет, мир, от Lua"
|
||||
for w in utf8.gmatch(s, "[^%p%d%s%c]+") do
|
||||
print(w)
|
||||
end
|
||||
--[[
|
||||
Привет
|
||||
мир
|
||||
от
|
||||
Lua
|
||||
]]--
|
||||
|
||||
local t = {}
|
||||
s = "from=world, to=Lua"
|
||||
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
|
||||
t[k] = v
|
||||
end
|
||||
for k,v in pairs(t) do
|
||||
print(k,v)
|
||||
end
|
||||
--[[
|
||||
to Lua
|
||||
from world
|
||||
]]--
|
||||
|
||||
t = {}
|
||||
s = "从=世界, 到=Lua"
|
||||
for k, v in utf8.gmatch(s, "([^%p%s%c]+)=([^%p%s%c]+)") do
|
||||
t[k] = v
|
||||
end
|
||||
for k,v in pairs(t) do
|
||||
print(k,v)
|
||||
end
|
||||
--[[
|
||||
到 Lua
|
||||
从 世界
|
||||
]]--
|
||||
|
||||
local x = string.gsub("hello world", "(%w+)", "%1 %1")
|
||||
print(x)
|
||||
--hello hello world world
|
||||
|
||||
x = utf8.gsub("Ahoj světe", "([^%p%s%c]+)", "%1 %1")
|
||||
print(x)
|
||||
--Ahoj Ahoj světe světe
|
||||
|
||||
x = string.gsub("hello world", "%w+", "%0 %0", 1)
|
||||
print(x)
|
||||
--hello hello world
|
||||
|
||||
x = utf8.gsub("Ahoj světe", "[^%p%s%c]+", "%0 %0", 1)
|
||||
print(x)
|
||||
--Ahoj Ahoj světe
|
||||
|
||||
x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
|
||||
print(x)
|
||||
--world hello Lua from
|
||||
|
||||
x = utf8.gsub("γεια κόσμο από Lua", "([^%p%s%c]+)%s*([^%p%s%c]+)", "%2 %1")
|
||||
print(x)
|
||||
--κόσμο γεια Lua από
|
||||
```
|
||||
Notice, there are some classes that can work only with latin(ASCII) symbols,
|
||||
for details see: https://github.com/Stepets/utf8.lua/blob/master/utf8.lua#L470
|
||||
|
||||
Of course you can do this trick:
|
||||
```Lua
|
||||
for k,v in pairs(utf8) do
|
||||
string[k] = v
|
||||
end
|
||||
```
|
||||
But this can lead to very strange errors. You were warned.
|
||||
|
||||
A little bit more interesting examples:
|
||||
```Lua
|
||||
local utf8 = require 'utf8'
|
||||
for k,v in pairs(utf8) do
|
||||
string[k] = v
|
||||
end
|
||||
|
||||
local str = "пыщпыщ ололоо я водитель нло"
|
||||
print(str:find("(.л.+)н"))
|
||||
-- 8 26 ололоо я водитель
|
||||
|
||||
print(str:gsub("ло+", "보라"))
|
||||
-- пыщпыщ о보라보라 я водитель н보라 3
|
||||
|
||||
print(str:match("^п[лопыщ ]*я"))
|
||||
-- пыщпыщ ололоо я
|
||||
```
|
||||
1045
runtime/plugins/autoclose/utf8/utf8.lua
Normal file
1045
runtime/plugins/autoclose/utf8/utf8.lua
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,17 @@
|
||||
if GetOption("ftoptions") == nil then
|
||||
AddOption("ftoptions", true)
|
||||
end
|
||||
|
||||
function onViewOpen(view)
|
||||
if not GetOption("ftoptions") then
|
||||
return
|
||||
end
|
||||
|
||||
local ft = view.Buf.Settings["filetype"]
|
||||
|
||||
if ft == "makefile" or ft == "go" then
|
||||
SetOption("tabstospaces", "off")
|
||||
elseif ft == "python" then
|
||||
elseif ft == "python" or ft == "python2" or ft == "python3" then
|
||||
SetOption("tabstospaces", "on")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,15 +12,15 @@ end
|
||||
function runLinter()
|
||||
local ft = CurView().Buf:FileType()
|
||||
local file = CurView().Buf.Path
|
||||
local devnull = "/dev/null"
|
||||
local temp = os.getenv("TMPDIR")
|
||||
local dir = DirectoryName(file)
|
||||
if OS == "windows" then
|
||||
devnull = "NUL"
|
||||
temp = os.getenv("TEMP")
|
||||
else
|
||||
devnull = "/dev/null"
|
||||
end
|
||||
if ft == "go" then
|
||||
lint("gobuild", "go", {"build", "-o", devnull}, "%f:%l: %m")
|
||||
lint("golint", "golint", {CurView().Buf.Path}, "%f:%l:%d+: %m")
|
||||
lint("golint", "golint", {file}, "%f:%l:%d+: %m")
|
||||
elseif ft == "lua" then
|
||||
lint("luacheck", "luacheck", {"--no-color", file}, "%f:%l:%d+: %m")
|
||||
elseif ft == "python" then
|
||||
@@ -29,18 +29,26 @@ function runLinter()
|
||||
lint("pylint", "pylint", {"--output-format=parseable", "--reports=no", file}, "%f:%l: %m")
|
||||
elseif ft == "c" then
|
||||
lint("gcc", "gcc", {"-fsyntax-only", "-Wall", "-Wextra", file}, "%f:%l:%d+:.+: %m")
|
||||
elseif ft == "swift" then
|
||||
elseif ft == "c++" then
|
||||
lint("gcc", "gcc", {"-fsyntax-only","-std=c++14", "-Wall", "-Wextra", file}, "%f:%l:%d+:.+: %m")
|
||||
elseif ft == "swift" and OS == "darwin" then
|
||||
lint("switfc", "xcrun", {"swiftc", file}, "%f:%l:%d+:.+: %m")
|
||||
elseif ft == "swift" and OS == "linux" then
|
||||
lint("switfc", "swiftc", {file}, "%f:%l:%d+:.+: %m")
|
||||
elseif ft == "Objective-C" then
|
||||
lint("clang", "xcrun", {"clang", "-fsyntax-only", "-Wall", "-Wextra", file}, "%f:%l:%d+:.+: %m")
|
||||
elseif ft == "d" then
|
||||
lint("dmd", "dmd", {"-color=off", "-o-", "-w", "-wi", "-c", file}, "%f%(%l%):.+: %m")
|
||||
elseif ft == "java" then
|
||||
lint("javac", "javac", {"-d", temp, file}, "%f:%l: error: %m")
|
||||
lint("javac", "javac", {"-d", dir, file}, "%f:%l: error: %m")
|
||||
elseif ft == "javascript" then
|
||||
lint("jshint", "jshint", {file}, "%f: line %l,.+, %m")
|
||||
elseif ft == "nim" then
|
||||
lint("nim", "nim", {"check", "--listFullPaths", "--stdout", "--hints:off", file}, "%f.%l, %d+. %m")
|
||||
elseif string.match(ft, "literate") then
|
||||
lint("literate", "lit", {"-c", file}, "%f:%l:%m")
|
||||
elseif ft == "yaml" then
|
||||
lint("yaml", "yamllint", {"--format", "parsable", file}, "%f:%l:%d+:.+ %m")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
5
runtime/plugins/literate/README.md
Normal file
5
runtime/plugins/literate/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Literate Micro
|
||||
|
||||
Support for reading `.lit` files from [zyedidia/Literate](https://github.com/zyedidia/Literate).
|
||||
|
||||
This plugin will automatically detect the filetype and highlight the correct language inside the code blocks.
|
||||
53
runtime/plugins/literate/literate.lua
Normal file
53
runtime/plugins/literate/literate.lua
Normal file
@@ -0,0 +1,53 @@
|
||||
VERSION = "1.0.0"
|
||||
|
||||
function startswith(str, start)
|
||||
return string.sub(str,1,string.len(start))==start
|
||||
end
|
||||
|
||||
function endswith(str, endStr)
|
||||
return endStr=='' or string.sub(str,-string.len(endStr))==endStr
|
||||
end
|
||||
|
||||
function split(string, sep)
|
||||
local sep, fields = sep or ":", {}
|
||||
local pattern = string.format("([^%s]+)", sep)
|
||||
string:gsub(pattern, function(c) fields[#fields+1] = c end)
|
||||
return fields
|
||||
end
|
||||
|
||||
function onViewOpen(view)
|
||||
if not endswith(view.Buf.Path, ".lit") then
|
||||
return
|
||||
end
|
||||
|
||||
local codetype = "unknown"
|
||||
for i=1,view.Buf.NumLines do
|
||||
local line = view.Buf:Line(i-1)
|
||||
if startswith(line, "@code_type") then
|
||||
codetype = split(line, " ")[2]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local syntaxFile = ""
|
||||
syntaxFile = syntaxFile .. "filetype: literate-" .. codetype .. "\n"
|
||||
syntaxFile = syntaxFile .. "detect:\n"
|
||||
syntaxFile = syntaxFile .. " filename: \"\\\\.lit$\"\n"
|
||||
syntaxFile = syntaxFile .. "rules:\n"
|
||||
syntaxFile = syntaxFile .. " - include: \"markdown\"\n"
|
||||
syntaxFile = syntaxFile .. " - special: \"^(@s|@title|@code_type|@comment_type|@include|@change|@change_end)\"\n"
|
||||
syntaxFile = syntaxFile .. " - special: \"(@add_css|@overwrite_css|@colorscheme|@compiler|@error_format|@book)\"\n"
|
||||
syntaxFile = syntaxFile .. " - default:\n"
|
||||
syntaxFile = syntaxFile .. " start: \"---.*$\"\n"
|
||||
syntaxFile = syntaxFile .. " end: \"---$\"\n"
|
||||
syntaxFile = syntaxFile .. " limit-group: \"identifier\"\n"
|
||||
syntaxFile = syntaxFile .. " rules:\n"
|
||||
syntaxFile = syntaxFile .. " - special:\n"
|
||||
syntaxFile = syntaxFile .. " start: \"@\\\\{\"\n"
|
||||
syntaxFile = syntaxFile .. " end: \"\\\\}\"\n"
|
||||
syntaxFile = syntaxFile .. " rules: []\n"
|
||||
syntaxFile = syntaxFile .. " - include: " .. codetype .. "\n"
|
||||
|
||||
AddRuntimeFileFromMemory("literate", "syntax", "literate.yaml", syntaxFile)
|
||||
Reload()
|
||||
end
|
||||
@@ -1,20 +0,0 @@
|
||||
## Syntax highlighting for Dockerfiles
|
||||
syntax "dockerfile" "Dockerfile[^/]*$" "\.dockerfile$"
|
||||
|
||||
## Keywords
|
||||
color keyword (i) "^(FROM|MAINTAINER|RUN|CMD|LABEL|EXPOSE|ENV|ADD|COPY|ENTRYPOINT|VOLUME|USER|WORKDIR|ONBUILD|ARG|HEALTHCHECK|STOPSIGNAL|SHELL)[[:space:]]"
|
||||
|
||||
## Brackets & parenthesis
|
||||
color statement "(\(|\)|\[|\])"
|
||||
|
||||
## Double ampersand
|
||||
color special "&&"
|
||||
|
||||
## Comments
|
||||
color comment (i) "^[[:space:]]*#.*$"
|
||||
|
||||
## Strings, single-quoted
|
||||
color constant.string "'([^']|(\\'))*'" "%[qw]\{[^}]*\}" "%[qw]\([^)]*\)" "%[qw]<[^>]*>" "%[qw]\[[^]]*\]" "%[qw]\$[^$]*\$" "%[qw]\^[^^]*\^" "%[qw]![^!]*!"
|
||||
|
||||
## Strings, double-quoted
|
||||
color constant.string ""([^"]|(\\"))*"" "%[QW]?\{[^}]*\}" "%[QW]?\([^)]*\)" "%[QW]?<[^>]*>" "%[QW]?\[[^]]*\]" "%[QW]?\$[^$]*\$" "%[QW]?\^[^^]*\^" "%[QW]?![^!]*!"
|
||||
@@ -1,15 +1,22 @@
|
||||
micro syntax files
|
||||
Copyright (C) 2016+ Zachary Yedidia et al.
|
||||
Micro's syntax files are licensed under the MIT "Expat" License:
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
Copyright (c) 2016: Zachary Yedidia, Collin Warren, et al.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
export
|
||||
:=
|
||||
error
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
# Syntax Files
|
||||
|
||||
Here are micro's syntax files.
|
||||
|
||||
Each yaml file specifies how to detect the filetype based on file extension or headers (first line of the file).
|
||||
Then there are patterns and regions linked to highlight groups which tell micro how to highlight that filetype.
|
||||
|
||||
Making your own syntax files is very simple. I recommend you check the file after you are finished with the
|
||||
[`syntax_checker.go`](./syntax_checker.go) program (located in this directory). Just place your yaml syntax
|
||||
file in the current directory and run `go run syntax_checker.go` and it will check every file. If there are no
|
||||
errors it will print `No issues!`.
|
||||
|
||||
You can read more about how to write syntax files (and colorschemes) in the [colors](../help/colors.md) documentation.
|
||||
|
||||
# Legacy '.micro' filetype
|
||||
|
||||
Micro used to use the `.micro` filetype for syntax files which is no longer supported. If you have `.micro`
|
||||
syntax files that you would like to convert to the new filetype, you can use the [`syntax_converter.go`](./syntax_converter.go) program (also located in this directory):
|
||||
|
||||
```
|
||||
$ go run syntax_converter.go c.micro > c.yaml
|
||||
```
|
||||
|
||||
Most the the syntax files here have been converted using that tool.
|
||||
|
||||
Note that the tool isn't perfect and though it is unlikely, you may run into some small issues that you will have to fix manually
|
||||
(about 4 files from this directory had issues after being converted).
|
||||
=======
|
||||
# Micro syntax highlighting files
|
||||
|
||||
These are the syntax highlighting files for micro. To install them, just
|
||||
@@ -7,12 +35,11 @@ They are taken from Nano, specifically from [this repository](https://github.com
|
||||
Micro syntax files are almost identical to Nano's, except for some key differences:
|
||||
|
||||
* Micro does not use `icolor`. Instead, for a case insensitive match, use the case insensitive flag (`i`) in the regular expression
|
||||
* For example, `icolor green ".*"` would become `color green (i) ".*"`
|
||||
* For example, `icolor green ".*"` would become `color green "(?i).*"`
|
||||
|
||||
# Using with colorschemes
|
||||
|
||||
Not all of these files have been converted to use micro's colorscheme feature. Most of them just hardcode the colors, which
|
||||
can be problematic depending on the colorscheme you use.
|
||||
Not all of these files have been converted to use micro's colorscheme feature. Most of them just hardcode the colors, which can be problematic depending on the colorscheme you use.
|
||||
|
||||
Here is a list of the files that have been converted to properly use colorschemes:
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
# Apache files
|
||||
syntax "apacheconf" "httpd\.conf|mime\.types|vhosts\.d\\*|\.htaccess"
|
||||
color yellow ".+"
|
||||
color brightcyan "(AcceptMutex|AcceptPathInfo|AccessFileName|Action|AddAlt|AddAltByEncoding|AddAltByType|AddCharset|AddDefaultCharset|AddDescription|AddEncoding)"
|
||||
color brightcyan "(AddHandler|AddIcon|AddIconByEncoding|AddIconByType|AddInputFilter|AddLanguage|AddModuleInfo|AddOutputFilter|AddOutputFilterByType|AddType|Alias|AliasMatch)"
|
||||
color brightcyan "(Allow|AllowCONNECT|AllowEncodedSlashes|AllowOverride|Anonymous|Anonymous_Authoritative|Anonymous_LogEmail|Anonymous_MustGiveEmail|Anonymous_NoUserID)"
|
||||
color brightcyan "(Anonymous_VerifyEmail|AssignUserID|AuthAuthoritative|AuthDBMAuthoritative|AuthDBMGroupFile|AuthDBMType|AuthDBMUserFile|AuthDigestAlgorithm)"
|
||||
color brightcyan "(AuthDigestDomain|AuthDigestFile|AuthDigestGroupFile|AuthDigestNcCheck|AuthDigestNonceFormat|AuthDigestNonceLifetime|AuthDigestQop|AuthDigestShmemSize)"
|
||||
color brightcyan "(AuthGroupFile|AuthLDAPAuthoritative|AuthLDAPBindDN|AuthLDAPBindPassword|AuthLDAPCharsetConfig|AuthLDAPCompareDNOnServer|AuthLDAPDereferenceAliases)"
|
||||
color brightcyan "(AuthLDAPEnabled|AuthLDAPFrontPageHack|AuthLDAPGroupAttribute|AuthLDAPGroupAttributeIsDN|AuthLDAPRemoteUserIsDN|AuthLDAPUrl|AuthName|AuthType|AuthUserFile)"
|
||||
color brightcyan "(BrowserMatch|BrowserMatchNoCase|BS2000Account|BufferedLogs|CacheDefaultExpire|CacheDirLength|CacheDirLevels|CacheDisable|CacheEnable|CacheExpiryCheck)"
|
||||
color brightcyan "(CacheFile|CacheForceCompletion|CacheGcClean|CacheGcDaily|CacheGcInterval|CacheGcMemUsage|CacheGcUnused|CacheIgnoreCacheControl|CacheIgnoreHeaders)"
|
||||
color brightcyan "(CacheIgnoreNoLastMod|CacheLastModifiedFactor|CacheMaxExpire|CacheMaxFileSize|CacheMinFileSize|CacheNegotiatedDocs|CacheRoot|CacheSize|CacheTimeMargin)"
|
||||
color brightcyan "(CGIMapExtension|CharsetDefault|CharsetOptions|CharsetSourceEnc|CheckSpelling|ChildPerUserID|ContentDigest|CookieDomain|CookieExpires|CookieLog|CookieName)"
|
||||
color brightcyan "(CookieStyle|CookieTracking|CoreDumpDirectory|CustomLog|Dav|DavDepthInfinity|DavLockDB|DavMinTimeout|DefaultIcon|DefaultLanguage|DefaultType)"
|
||||
color brightcyan "(DeflateBufferSize|DeflateCompressionLevel|DeflateFilterNote|DeflateMemLevel|DeflateWindowSize|Deny|Directory|DirectoryIndex|DirectoryMatch|DirectorySlash)"
|
||||
color brightcyan "(DocumentRoot|DumpIOInput|DumpIOOutput|EnableExceptionHook|EnableMMAP|EnableSendfile|ErrorDocument|ErrorLog|Example|ExpiresActive|ExpiresByType)"
|
||||
color brightcyan "(ExpiresDefault|ExtendedStatus|ExtFilterDefine|ExtFilterOptions|FileETag|Files|FilesMatch|ForceLanguagePriority|ForceType|ForensicLog|Group|Header)"
|
||||
color brightcyan "(HeaderName|HostnameLookups|IdentityCheck|IfDefine|IfModule|IfVersion|ImapBase|ImapDefault|ImapMenu|Include|IndexIgnore|IndexOptions|IndexOrderDefault)"
|
||||
color brightcyan "(ISAPIAppendLogToErrors|ISAPIAppendLogToQuery|ISAPICacheFile|ISAPIFakeAsync|ISAPILogNotSupported|ISAPIReadAheadBuffer|KeepAlive|KeepAliveTimeout)"
|
||||
color brightcyan "(LanguagePriority|LDAPCacheEntries|LDAPCacheTTL|LDAPConnectionTimeout|LDAPOpCacheEntries|LDAPOpCacheTTL|LDAPSharedCacheFile|LDAPSharedCacheSize)"
|
||||
color brightcyan "(LDAPTrustedCA|LDAPTrustedCAType|Limit|LimitExcept|LimitInternalRecursion|LimitRequestBody|LimitRequestFields|LimitRequestFieldSize|LimitRequestLine)"
|
||||
color brightcyan "(LimitXMLRequestBody|Listen|ListenBackLog|LoadFile|LoadModule|Location|LocationMatch|LockFile|LogFormat|LogLevel|MaxClients|MaxKeepAliveRequests)"
|
||||
color brightcyan "(MaxMemFree|MaxRequestsPerChild|MaxRequestsPerThread|MaxSpareServers|MaxSpareThreads|MaxThreads|MaxThreadsPerChild|MCacheMaxObjectCount|MCacheMaxObjectSize)"
|
||||
color brightcyan "(MCacheMaxStreamingBuffer|MCacheMinObjectSize|MCacheRemovalAlgorithm|MCacheSize|MetaDir|MetaFiles|MetaSuffix|MimeMagicFile|MinSpareServers|MinSpareThreads)"
|
||||
color brightcyan "(MMapFile|ModMimeUsePathInfo|MultiviewsMatch|NameVirtualHost|NoProxy|NumServers|NWSSLTrustedCerts|NWSSLUpgradeable|Options|Order|PassEnv|PidFile)"
|
||||
color brightcyan "(ProtocolEcho|Proxy|ProxyBadHeader|ProxyBlock|ProxyDomain|ProxyErrorOverride|ProxyIOBufferSize|ProxyMatch|ProxyMaxForwards|ProxyPass|ProxyPassReverse)"
|
||||
color brightcyan "(ProxyPreserveHost|ProxyReceiveBufferSize|ProxyRemote|ProxyRemoteMatch|ProxyRequests|ProxyTimeout|ProxyVia|ReadmeName|Redirect|RedirectMatch)"
|
||||
color brightcyan "(RedirectPermanent|RedirectTemp|RemoveCharset|RemoveEncoding|RemoveHandler|RemoveInputFilter|RemoveLanguage|RemoveOutputFilter|RemoveType|RequestHeader)"
|
||||
color brightcyan "(Require|RewriteBase|RewriteCond|RewriteEngine|RewriteLock|RewriteLog|RewriteLogLevel|RewriteMap|RewriteOptions|RewriteRule|RLimitCPU|RLimitMEM|RLimitNPROC)"
|
||||
color brightcyan "(Satisfy|ScoreBoardFile|Script|ScriptAlias|ScriptAliasMatch|ScriptInterpreterSource|ScriptLog|ScriptLogBuffer|ScriptLogLength|ScriptSock|SecureListen)"
|
||||
color brightcyan "(SendBufferSize|ServerAdmin|ServerAlias|ServerLimit|ServerName|ServerPath|ServerRoot|ServerSignature|ServerTokens|SetEnv|SetEnvIf|SetEnvIfNoCase|SetHandler)"
|
||||
color brightcyan "(SetInputFilter|SetOutputFilter|SSIEndTag|SSIErrorMsg|SSIStartTag|SSITimeFormat|SSIUndefinedEcho|SSLCACertificateFile|SSLCACertificatePath)"
|
||||
color brightcyan "(SSLCARevocationFile|SSLCARevocationPath|SSLCertificateChainFile|SSLCertificateFile|SSLCertificateKeyFile|SSLCipherSuite|SSLEngine|SSLMutex|SSLOptions)"
|
||||
color brightcyan "(SSLPassPhraseDialog|SSLProtocol|SSLProxyCACertificateFile|SSLProxyCACertificatePath|SSLProxyCARevocationFile|SSLProxyCARevocationPath|SSLProxyCipherSuite)"
|
||||
color brightcyan "(SSLProxyEngine|SSLProxyMachineCertificateFile|SSLProxyMachineCertificatePath|SSLProxyProtocol|SSLProxyVerify|SSLProxyVerifyDepth|SSLRandomSeed|SSLRequire)"
|
||||
color brightcyan "(SSLRequireSSL|SSLSessionCache|SSLSessionCacheTimeout|SSLUserName|SSLVerifyClient|SSLVerifyDepth|StartServers|StartThreads|SuexecUserGroup|ThreadLimit)"
|
||||
color brightcyan "(ThreadsPerChild|ThreadStackSize|TimeOut|TraceEnable|TransferLog|TypesConfig|UnsetEnv|UseCanonicalName|User|UserDir|VirtualDocumentRoot)"
|
||||
color brightcyan "(VirtualDocumentRootIP|VirtualHost|VirtualScriptAlias|VirtualScriptAliasIP|Win32DisableAcceptEx|XBitHack)"
|
||||
color yellow "<[^>]+>"
|
||||
color brightcyan "</?[A-Za-z]+"
|
||||
color brightcyan "(<|</|>)"
|
||||
color green "\"(\\.|[^\"])*\""
|
||||
color white "#.*"
|
||||
59
runtime/syntax/apacheconf.yaml
Normal file
59
runtime/syntax/apacheconf.yaml
Normal file
@@ -0,0 +1,59 @@
|
||||
filetype: apacheconf
|
||||
|
||||
detect:
|
||||
filename: "httpd\\.conf|mime\\.types|vhosts\\.d\\\\*|\\.htaccess"
|
||||
|
||||
rules:
|
||||
- identifier: "(AcceptMutex|AcceptPathInfo|AccessFileName|Action|AddAlt|AddAltByEncoding|AddAltByType|AddCharset|AddDefaultCharset|AddDescription|AddEncoding)"
|
||||
- identifier: "(AddHandler|AddIcon|AddIconByEncoding|AddIconByType|AddInputFilter|AddLanguage|AddModuleInfo|AddOutputFilter|AddOutputFilterByType|AddType|Alias|AliasMatch)"
|
||||
- identifier: "(Allow|AllowCONNECT|AllowEncodedSlashes|AllowOverride|Anonymous|Anonymous_Authoritative|Anonymous_LogEmail|Anonymous_MustGiveEmail|Anonymous_NoUserID)"
|
||||
- identifier: "(Anonymous_VerifyEmail|AssignUserID|AuthAuthoritative|AuthDBMAuthoritative|AuthDBMGroupFile|AuthDBMType|AuthDBMUserFile|AuthDigestAlgorithm)"
|
||||
- identifier: "(AuthDigestDomain|AuthDigestFile|AuthDigestGroupFile|AuthDigestNcCheck|AuthDigestNonceFormat|AuthDigestNonceLifetime|AuthDigestQop|AuthDigestShmemSize)"
|
||||
- identifier: "(AuthGroupFile|AuthLDAPAuthoritative|AuthLDAPBindDN|AuthLDAPBindPassword|AuthLDAPCharsetConfig|AuthLDAPCompareDNOnServer|AuthLDAPDereferenceAliases)"
|
||||
- identifier: "(AuthLDAPEnabled|AuthLDAPFrontPageHack|AuthLDAPGroupAttribute|AuthLDAPGroupAttributeIsDN|AuthLDAPRemoteUserIsDN|AuthLDAPUrl|AuthName|AuthType|AuthUserFile)"
|
||||
- identifier: "(BrowserMatch|BrowserMatchNoCase|BS2000Account|BufferedLogs|CacheDefaultExpire|CacheDirLength|CacheDirLevels|CacheDisable|CacheEnable|CacheExpiryCheck)"
|
||||
- identifier: "(CacheFile|CacheForceCompletion|CacheGcClean|CacheGcDaily|CacheGcInterval|CacheGcMemUsage|CacheGcUnused|CacheIgnoreCacheControl|CacheIgnoreHeaders)"
|
||||
- identifier: "(CacheIgnoreNoLastMod|CacheLastModifiedFactor|CacheMaxExpire|CacheMaxFileSize|CacheMinFileSize|CacheNegotiatedDocs|CacheRoot|CacheSize|CacheTimeMargin)"
|
||||
- identifier: "(CGIMapExtension|CharsetDefault|CharsetOptions|CharsetSourceEnc|CheckSpelling|ChildPerUserID|ContentDigest|CookieDomain|CookieExpires|CookieLog|CookieName)"
|
||||
- identifier: "(CookieStyle|CookieTracking|CoreDumpDirectory|CustomLog|Dav|DavDepthInfinity|DavLockDB|DavMinTimeout|DefaultIcon|DefaultLanguage|DefaultType)"
|
||||
- identifier: "(DeflateBufferSize|DeflateCompressionLevel|DeflateFilterNote|DeflateMemLevel|DeflateWindowSize|Deny|Directory|DirectoryIndex|DirectoryMatch|DirectorySlash)"
|
||||
- identifier: "(DocumentRoot|DumpIOInput|DumpIOOutput|EnableExceptionHook|EnableMMAP|EnableSendfile|ErrorDocument|ErrorLog|Example|ExpiresActive|ExpiresByType)"
|
||||
- identifier: "(ExpiresDefault|ExtendedStatus|ExtFilterDefine|ExtFilterOptions|FileETag|Files|FilesMatch|ForceLanguagePriority|ForceType|ForensicLog|Group|Header)"
|
||||
- identifier: "(HeaderName|HostnameLookups|IdentityCheck|IfDefine|IfModule|IfVersion|ImapBase|ImapDefault|ImapMenu|Include|IndexIgnore|IndexOptions|IndexOrderDefault)"
|
||||
- identifier: "(ISAPIAppendLogToErrors|ISAPIAppendLogToQuery|ISAPICacheFile|ISAPIFakeAsync|ISAPILogNotSupported|ISAPIReadAheadBuffer|KeepAlive|KeepAliveTimeout)"
|
||||
- identifier: "(LanguagePriority|LDAPCacheEntries|LDAPCacheTTL|LDAPConnectionTimeout|LDAPOpCacheEntries|LDAPOpCacheTTL|LDAPSharedCacheFile|LDAPSharedCacheSize)"
|
||||
- identifier: "(LDAPTrustedCA|LDAPTrustedCAType|Limit|LimitExcept|LimitInternalRecursion|LimitRequestBody|LimitRequestFields|LimitRequestFieldSize|LimitRequestLine)"
|
||||
- identifier: "(LimitXMLRequestBody|Listen|ListenBackLog|LoadFile|LoadModule|Location|LocationMatch|LockFile|LogFormat|LogLevel|MaxClients|MaxKeepAliveRequests)"
|
||||
- identifier: "(MaxMemFree|MaxRequestsPerChild|MaxRequestsPerThread|MaxSpareServers|MaxSpareThreads|MaxThreads|MaxThreadsPerChild|MCacheMaxObjectCount|MCacheMaxObjectSize)"
|
||||
- identifier: "(MCacheMaxStreamingBuffer|MCacheMinObjectSize|MCacheRemovalAlgorithm|MCacheSize|MetaDir|MetaFiles|MetaSuffix|MimeMagicFile|MinSpareServers|MinSpareThreads)"
|
||||
- identifier: "(MMapFile|ModMimeUsePathInfo|MultiviewsMatch|NameVirtualHost|NoProxy|NumServers|NWSSLTrustedCerts|NWSSLUpgradeable|Options|Order|PassEnv|PidFile)"
|
||||
- identifier: "(ProtocolEcho|Proxy|ProxyBadHeader|ProxyBlock|ProxyDomain|ProxyErrorOverride|ProxyIOBufferSize|ProxyMatch|ProxyMaxForwards|ProxyPass|ProxyPassReverse)"
|
||||
- identifier: "(ProxyPreserveHost|ProxyReceiveBufferSize|ProxyRemote|ProxyRemoteMatch|ProxyRequests|ProxyTimeout|ProxyVia|ReadmeName|Redirect|RedirectMatch)"
|
||||
- identifier: "(RedirectPermanent|RedirectTemp|RemoveCharset|RemoveEncoding|RemoveHandler|RemoveInputFilter|RemoveLanguage|RemoveOutputFilter|RemoveType|RequestHeader)"
|
||||
- identifier: "(Require|RewriteBase|RewriteCond|RewriteEngine|RewriteLock|RewriteLog|RewriteLogLevel|RewriteMap|RewriteOptions|RewriteRule|RLimitCPU|RLimitMEM|RLimitNPROC)"
|
||||
- identifier: "(Satisfy|ScoreBoardFile|Script|ScriptAlias|ScriptAliasMatch|ScriptInterpreterSource|ScriptLog|ScriptLogBuffer|ScriptLogLength|ScriptSock|SecureListen)"
|
||||
- identifier: "(SendBufferSize|ServerAdmin|ServerAlias|ServerLimit|ServerName|ServerPath|ServerRoot|ServerSignature|ServerTokens|SetEnv|SetEnvIf|SetEnvIfNoCase|SetHandler)"
|
||||
- identifier: "(SetInputFilter|SetOutputFilter|SSIEndTag|SSIErrorMsg|SSIStartTag|SSITimeFormat|SSIUndefinedEcho|SSLCACertificateFile|SSLCACertificatePath)"
|
||||
- identifier: "(SSLCARevocationFile|SSLCARevocationPath|SSLCertificateChainFile|SSLCertificateFile|SSLCertificateKeyFile|SSLCipherSuite|SSLEngine|SSLMutex|SSLOptions)"
|
||||
- identifier: "(SSLPassPhraseDialog|SSLProtocol|SSLProxyCACertificateFile|SSLProxyCACertificatePath|SSLProxyCARevocationFile|SSLProxyCARevocationPath|SSLProxyCipherSuite)"
|
||||
- identifier: "(SSLProxyEngine|SSLProxyMachineCertificateFile|SSLProxyMachineCertificatePath|SSLProxyProtocol|SSLProxyVerify|SSLProxyVerifyDepth|SSLRandomSeed|SSLRequire)"
|
||||
- identifier: "(SSLRequireSSL|SSLSessionCache|SSLSessionCacheTimeout|SSLUserName|SSLVerifyClient|SSLVerifyDepth|StartServers|StartThreads|SuexecUserGroup|ThreadLimit)"
|
||||
- identifier: "(ThreadsPerChild|ThreadStackSize|TimeOut|TraceEnable|TransferLog|TypesConfig|UnsetEnv|UseCanonicalName|User|UserDir|VirtualDocumentRoot)"
|
||||
- identifier: "(VirtualDocumentRootIP|VirtualHost|VirtualScriptAlias|VirtualScriptAliasIP|Win32DisableAcceptEx|XBitHack)"
|
||||
- symbol.tag: "<[^>]+>"
|
||||
- identifier: "</?[A-Za-z]+"
|
||||
- identifier: "(<|</|>)"
|
||||
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- comment:
|
||||
start: "#"
|
||||
end: "$"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
|
||||
## FILENAME: arduino.nanorc
|
||||
##
|
||||
## DESCRIPTION: The arduino.nanorc syntax files allows syntax highlighting
|
||||
## for Arduino sketch files in the GNU nano text editor.
|
||||
##
|
||||
## Maintainer: Nicholas Wilde
|
||||
## Version: 0.1
|
||||
## DATE: 06/23/2011
|
||||
##
|
||||
## HOMEPAGE: http://code.google.com/p/arduino-nano-editor-syntax/
|
||||
##
|
||||
## COMMENTS: -Most of the code was taken from the c.nanorc code found with
|
||||
## GNU nano 2.2.6.
|
||||
## -Direction was taken from the arduino vim syntax code by johannes
|
||||
## <https://bitbucket.org/johannes/arduino-vim-syntax/>
|
||||
## -Tested on Ubuntu Server 11.04 Natty Narwhal and GNU nano 2.2.6
|
||||
##
|
||||
## DIRECTIONS: For Ubuntu Server 11.04 Natty Narwhal:
|
||||
## -Move this file <arduino.nanorc> to the nano directory
|
||||
## /usr/share/nano/
|
||||
## -Add arduino.nanorc reference to the nanorc settings file
|
||||
## /etc/nanorc
|
||||
## ...
|
||||
## ## Arduino
|
||||
## /usr/share/nano/arduino.nanorc
|
||||
## ...
|
||||
|
||||
syntax "ino" "\.?ino$"
|
||||
|
||||
##
|
||||
color brightred "\<[A-Z_][0-9A-Z_]+\>"
|
||||
|
||||
##
|
||||
color green "\<((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\>"
|
||||
|
||||
## Constants
|
||||
green (i) "\<(HIGH|LOW|INPUT|OUTPUT)\>"
|
||||
|
||||
## Serial Print
|
||||
red (i) "\<(DEC|BIN|HEX|OCT|BYTE)\>"
|
||||
|
||||
## PI Constants
|
||||
green (i) "\<(PI|HALF_PI|TWO_PI)\>"
|
||||
|
||||
## ShiftOut
|
||||
green (i) "\<(LSBFIRST|MSBFIRST)\>"
|
||||
|
||||
## Attach Interrupt
|
||||
green (i) "\<(CHANGE|FALLING|RISING)\>"
|
||||
|
||||
## Analog Reference
|
||||
green (i) "\<(DEFAULT|EXTERNAL|INTERNAL|INTERNAL1V1|INTERNAL2V56)\>"
|
||||
|
||||
## === FUNCTIONS === ##
|
||||
|
||||
## Data Types
|
||||
color green "\<(boolean|byte|char|float|int|long|word)\>"
|
||||
|
||||
## Control Structions
|
||||
color brightyellow "\<(case|class|default|do|double|else|false|for|if|new|null|private|protected|public|short|signed|static|String|switch|this|throw|try|true|unsigned|void|while)\>"
|
||||
color magenta "\<(goto|continue|break|return)\>"
|
||||
|
||||
## Math
|
||||
color brightyellow "\<(abs|acos|asin|atan|atan2|ceil|constrain|cos|degrees|exp|floor|log|map|max|min|radians|random|randomSeed|round|sin|sq|sqrt|tan)\>"
|
||||
|
||||
## Bits & Bytes
|
||||
color brightyellow "\<(bitRead|bitWrite|bitSet|bitClear|bit|highByte|lowByte)\>"
|
||||
|
||||
## Analog I/O
|
||||
color brightyellow "\<(analogReference|analogRead|analogWrite)\>"
|
||||
|
||||
## External Interrupts
|
||||
color brightyellow "\<(attachInterrupt|detachInterrupt)\>"
|
||||
|
||||
## Time
|
||||
color brightyellow "\<(delay|delayMicroseconds|millis|micros)\>"
|
||||
|
||||
## Digital I/O
|
||||
color brightyellow "\<(pinMode|digitalWrite|digitalRead)\>"
|
||||
|
||||
## Interrupts
|
||||
color brightyellow "\<(interrupts|noInterrupts)\>"
|
||||
|
||||
## Advanced I/O
|
||||
color brightyellow "\<(noTone|pulseIn|shiftIn|shiftOut|tone)\>"
|
||||
|
||||
## Serial
|
||||
color magenta "\<(Serial|Serial1|Serial2|Serial3|begin|end|peek|read|print|println|available|flush)\>"
|
||||
|
||||
## Structure
|
||||
color brightyellow "\<(setup|loop)\>"
|
||||
|
||||
##
|
||||
color brightcyan "^[[:space:]]*#[[:space:]]*(define|include(_next)?|(un|ifn?)def|endif|el(if|se)|if|warning|error|pragma)"
|
||||
|
||||
##
|
||||
color brightmagenta "'([^']|(\\["'abfnrtv\\]))'" "'\\(([0-3]?[0-7]{1,2}))'" "'\\x[0-9A-Fa-f]{1,2}'"
|
||||
|
||||
## GCC builtins
|
||||
color cyan "__attribute__[[:space:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||
|
||||
## String highlighting. You will in general want your comments and
|
||||
## strings to come last, because syntax highlighting rules will be
|
||||
## applied in the order they are read in.
|
||||
color brightyellow "<[^= ]*>" ""(\\.|[^"])*""
|
||||
|
||||
## This string is VERY resource intensive!
|
||||
color brightyellow start=""(\\.|[^"])*\\[[:space:]]*$" end="^(\\.|[^"])*""
|
||||
|
||||
## Comments
|
||||
color brightblue "//.*"
|
||||
color brightblue start="/\*" end="\*/"
|
||||
|
||||
## Trailing whitespace
|
||||
color ,green "[[:space:]]+$"
|
||||
101
runtime/syntax/arduino.yaml
Normal file
101
runtime/syntax/arduino.yaml
Normal file
@@ -0,0 +1,101 @@
|
||||
filetype: ino
|
||||
|
||||
detect:
|
||||
filename: "\\.?ino$"
|
||||
|
||||
rules:
|
||||
- identifier: "\\b[A-Z_][0-9A-Z_]+\\b"
|
||||
|
||||
##
|
||||
- type: "\\b((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\\b"
|
||||
|
||||
## Constants
|
||||
- constant: "(?i)\\b(HIGH|LOW|INPUT|OUTPUT)\\b"
|
||||
|
||||
## Serial Print
|
||||
- constant: "(?i)\\b(DEC|BIN|HEX|OCT|BYTE)\\b"
|
||||
|
||||
## PI Constants
|
||||
- constant: "(?i)\\b(PI|HALF_PI|TWO_PI)\\b"
|
||||
|
||||
## ShiftOut
|
||||
- constant: "(?i)\\b(LSBFIRST|MSBFIRST)\\b"
|
||||
|
||||
## Attach Interrupt
|
||||
- constant: "(?i)\\b(CHANGE|FALLING|RISING)\\b"
|
||||
|
||||
## Analog Reference
|
||||
- constant: "(?i)\\b(DEFAULT|EXTERNAL|INTERNAL|INTERNAL1V1|INTERNAL2V56)\\b"
|
||||
|
||||
## === FUNCTIONS === ##
|
||||
|
||||
## Data Types
|
||||
- type: "\\b(boolean|byte|char|float|int|long|word)\\b"
|
||||
|
||||
## Control Structions
|
||||
- statement: "\\b(case|class|default|do|double|else|false|for|if|new|null|private|protected|public|short|signed|static|String|switch|this|throw|try|true|unsigned|void|while)\\b"
|
||||
- statement: "\\b(goto|continue|break|return)\\b"
|
||||
|
||||
## Math
|
||||
- identifier: "\\b(abs|acos|asin|atan|atan2|ceil|constrain|cos|degrees|exp|floor|log|map|max|min|radians|random|randomSeed|round|sin|sq|sqrt|tan)\\b"
|
||||
|
||||
## Bits & Bytes
|
||||
- identifier: "\\b(bitRead|bitWrite|bitSet|bitClear|bit|highByte|lowByte)\\b"
|
||||
|
||||
## Analog I/O
|
||||
- identifier: "\\b(analogReference|analogRead|analogWrite)\\b"
|
||||
|
||||
## External Interrupts
|
||||
- identifier: "\\b(attachInterrupt|detachInterrupt)\\b"
|
||||
|
||||
## Time
|
||||
- identifier: "\\b(delay|delayMicroseconds|millis|micros)\\b"
|
||||
|
||||
## Digital I/O
|
||||
- identifier: "\\b(pinMode|digitalWrite|digitalRead)\\b"
|
||||
|
||||
## Interrupts
|
||||
- identifier: "\\b(interrupts|noInterrupts)\\b"
|
||||
|
||||
## Advanced I/O
|
||||
- identifier: "\\b(noTone|pulseIn|shiftIn|shiftOut|tone)\\b"
|
||||
|
||||
## Serial
|
||||
- identifier: "\\b(Serial|Serial1|Serial2|Serial3|begin|end|peek|read|print|println|available|flush)\\b"
|
||||
|
||||
## Structure
|
||||
- identifier: "\\b(setup|loop)\\b"
|
||||
|
||||
##
|
||||
- statement: "^[[:space:]]*#[[:space:]]*(define|include(_next)?|(un|ifn?)def|endif|el(if|se)|if|warning|error|pragma)"
|
||||
|
||||
## GCC builtins
|
||||
- constant: "(__attribute__[[:space:]]*\\(\\([^)]*\\)\\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__)"
|
||||
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- constant.string:
|
||||
start: "'"
|
||||
end: "'"
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- preproc: "..+"
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- comment:
|
||||
start: "//"
|
||||
end: "$"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
|
||||
- comment:
|
||||
start: "/\\*"
|
||||
end: "\\*/"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
syntax "asciidoc" "\.(asc|asciidoc|adoc)$"
|
||||
|
||||
# main header
|
||||
color red "^====+$"
|
||||
# h1
|
||||
color red "^==[[:space:]].*$"
|
||||
color red "^----+$"
|
||||
# h2
|
||||
color magenta "^===[[:space:]].*$"
|
||||
color magenta "^~~~~+$"
|
||||
# h4
|
||||
color green "^====[[:space:]].*$"
|
||||
color green "^\^\^\^\^+$"
|
||||
# h5
|
||||
color brightblue "^=====[[:space:]].*$"
|
||||
color brightblue "^\+\+\+\++$"
|
||||
|
||||
# attributes
|
||||
color brightgreen ":.*:"
|
||||
color brightred "\{[a-z0-9]*\}"
|
||||
color red "\\\{[a-z0-9]*\}"
|
||||
color red "\+\+\+\{[a-z0-9]*\}\+\+\+"
|
||||
|
||||
# Paragraph Title
|
||||
color yellow "^\..*$"
|
||||
|
||||
# source
|
||||
color magenta "^\[(source,.+|NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]"
|
||||
|
||||
# Other markup
|
||||
color yellow ".*[[:space:]]\+$"
|
||||
color yellow "_[^_]+_"
|
||||
color yellow "\*[^\*]+\*"
|
||||
color yellow "\+[^\+]+\+"
|
||||
color yellow "`[^`]+`"
|
||||
color yellow "\^[^\^]+\^"
|
||||
color yellow "~[^~]+~"
|
||||
color yellow "'[^']+'"
|
||||
|
||||
color cyan "`{1,2}[^']+'{1,2}"
|
||||
|
||||
# bullets
|
||||
color brightmagenta "^[[:space:]]*[\*\.-]{1,5}[[:space:]]"
|
||||
|
||||
# anchors
|
||||
color brightwhite "\[\[.*\]\]"
|
||||
color brightwhite "<<.*>>"
|
||||
51
runtime/syntax/asciidoc.yaml
Normal file
51
runtime/syntax/asciidoc.yaml
Normal file
@@ -0,0 +1,51 @@
|
||||
filetype: asciidoc
|
||||
|
||||
detect:
|
||||
filename: "\\.(asc|asciidoc|adoc)$"
|
||||
|
||||
rules:
|
||||
# main header
|
||||
- preproc: "^====+$"
|
||||
# h1
|
||||
- statement: "^==[[:space:]].*$"
|
||||
- statement: "^----+$"
|
||||
# h2
|
||||
- symbol: "^===[[:space:]].*$"
|
||||
- symbol: "^~~~~+$"
|
||||
# h4
|
||||
- type: "^====[[:space:]].*$"
|
||||
- type: "^\\^\\^\\^\\^+$"
|
||||
# h5
|
||||
- constant: "^=====[[:space:]].*$"
|
||||
- constant: "^\\+\\+\\+\\++$"
|
||||
|
||||
# attributes
|
||||
- type.keyword: ":.*:"
|
||||
- identifier.macro: "\\{[a-z0-9]*\\}"
|
||||
- identifier: "\\\\\\{[a-z0-9]*\\}"
|
||||
- identifier: "\\+\\+\\+\\{[a-z0-9]*\\}\\+\\+\\+"
|
||||
|
||||
# Paragraph Title
|
||||
- statement: "^\\..*$"
|
||||
|
||||
# source
|
||||
- identifier: "^\\[(source,.+|NOTE|TIP|IMPORTANT|WARNING|CAUTION)\\]"
|
||||
|
||||
# Other markup
|
||||
- constant.string: ".*[[:space:]]\\+$"
|
||||
- constant.string: "_[^_]+_"
|
||||
- constant.string: "\\*[^\\*]+\\*"
|
||||
- constant.string: "\\+[^\\+]+\\+"
|
||||
- constant.string: "`[^`]+`"
|
||||
- constant.string: "\\^[^\\^]+\\^"
|
||||
- constant.string: "~[^~]+~"
|
||||
- constant.string: "'[^']+'"
|
||||
|
||||
- constant: "`{1,2}[^']+'{1,2}"
|
||||
|
||||
# bullets
|
||||
- symbol: "^[[:space:]]*[\\*\\.-]{1,5}[[:space:]]"
|
||||
|
||||
# anchors
|
||||
- "bold default": "\\[\\[.*\\]\\]"
|
||||
- "bold default": "<<.*>>"
|
||||
@@ -1,93 +0,0 @@
|
||||
## Made by Nickolay Ilyushin <nickolay02@inbox.ru>. Next line is from previous (first) version (no need for modifications :P)
|
||||
syntax "asm" "\.(S|s|asm)$"
|
||||
|
||||
# This file is made for NASM assembly
|
||||
|
||||
## Instructions
|
||||
# x86
|
||||
color statement "\b(?i)(mov|aaa|aad|aam|aas|adc|add|and|call|cbw|clc|cld|cli|cmc|cmp|cmpsb|cmpsw|cwd|daa|das|dec|div|esc|hlt|idiv|imul|in|inc|int|into|iret|ja|jae|jb|jbe|jc|je|jg|jge|jl|jle|jna|jnae|jnb|jnbe|jnc|jne|jng|jnge|jnl|jnle|jno|jnp|jns|jnz|jo|jp|jpe|jpo|js|jz|jcxz|jmp|lahf|lds|lea|les|lock|lodsb|lodsw|loop|loope|loopne|loopnz|loopz|movsb|movsw|mul|neg|nop|or|pop|popf|push|pushf|rcl|rcr|rep|repe|repne|repnz|repz|ret|retn|retf|rol|ror|sahf|sal|sar|sbb|scasb|scasw|shl|shr|stc|std|sti|stosb|stosw|sub|test|wait|xchg|xlat|xor)(?-i)\b"
|
||||
color statement "\b(?i)(bound|enter|ins|leave|outs|popa|pusha)(?-i)\b"
|
||||
color statement "\b(?i)(arpl|clts|lar|lgdt|lidt|lldt|lmsw|loadall|lsl|ltr|sgdt|sidt|sldt|smsw|str|verr|verw)(?-i)\b"
|
||||
color statement "\b(?i)(bsf|bsr|bt|btc|btr|bts|cdq|cmpsd|cwde|insd|iret|iretd|iretf|jecxz|lfs|lgs|lss|lodsd|loopw|loopew|loopnew|loopnzw|loopzw|loopd|looped|loopned|loopnzd|loopzd|cr|tr|dr|movsd|movsx|movzx|outsd|popad|popfd|pushad|pushfd|scasd|seta|setae|setb|setbe|setc|sete|setg|setge|setl|setle|setna|setnae|setnb|setnbe|setnc|setne|setng|setnge|setnl|setnle|setno|setnp|setns|setnz|seto|setp|setpe|setpo|sets|setz|shdl|shrd|stosd)(?-i)\b"
|
||||
color statement "\b(?i)(bswap|cmpxcgh|invd|invlpg|wbinvd|xadd)(?-i)\b"
|
||||
color statement "\b(?i)(cpuid|cmpxchg8b|rdmsr|rdtsc|wrmsr|rsm)(?-i)\b"
|
||||
color statement "\b(?i)(rdpmc)(?-i)\b"
|
||||
color statement "\b(?i)(syscall|sysret)(?-i)\b"
|
||||
color statement "\b(?i)(cmova|cmovae|cmovb|cmovbe|cmovc|cmove|cmovg|cmovge|cmovl|cmovle|cmovna|cmovnae|cmovnb|cmovnbe|cmovnc|cmovne|cmovng|cmovnge|cmovnle|cmovno|cmovpn|cmovns|cmovnz|cmovo|cmovp|cmovpe|cmovpo|cmovs|cmovz|sysenter|sysexit|ud2)(?-i)\b"
|
||||
color statement "\b(?i)(maskmovq|movntps|movntq|prefetch0|prefetch1|prefetch2|prefetchnta|sfence)(?-i)\b"
|
||||
color statement "\b(?i)(clflush|lfence|maskmovdqu|mfence|movntdq|movnti|movntpd|pause)(?-i)\b"
|
||||
color statement "\b(?i)(monitor|mwait)(?-i)\b"
|
||||
color statement "\b(?i)(cdqe|cqo|cmpsq|cmpxchg16b|iretq|jrcxz|lodsq|movsdx|popfq|pushfq|rdtscp|scasq|stosq|swapgs)(?-i)\b"
|
||||
color statement "\b(?i)(clgi|invlpga|skinit|stgi|vmload|vmmcall|vmrun|vmsave)(?-i)\b"
|
||||
color statement "\b(?i)(vmptrdl|vmptrst|vmclear|vmread|vmwrite|vmcall|vmlaunch|vmresume|vmxoff|vmxon)(?-i)\b"
|
||||
color statement "\b(?i)(lzcnt|popcnt)(?-i)\b"
|
||||
color statement "\b(?i)(bextr|blcfill|blci|blcic|blcmask|blcs|blsfill|blsic|t1mskc|tzmsk)(?-i)\b"
|
||||
|
||||
# x87
|
||||
color statement "\b(?i)(f2xm1|fabs|fadd|faddp|fbld|fbstp|fchs|fclex|fcom|fcomp|fcompp|fdecstp|fdisi|fdiv|fvidp|fdivr|fdivrp|feni|ffree|fiadd|ficom|ficomp|fidiv|fidivr|fild|fimul|fincstp|finit|fist|fistp|fisub|fisubr|fld|fld1|fldcw|fldenv|fldenvw|fldl2e|fldl2t|fldlg2|fldln2|fldpi|fldz|fmul|fmulp|fnclex|fndisi|fneni|fninit|fnop|fnsave|fnsavenew|fnstcw|fnstenv|fnstenvw|fnstsw|fpatan|fprem|fptan|frndint|frstor|frstorw|fsave|fsavew|fscale|fsqrt|fst|fstcw|fstenv|fstenvw|fstp|fstpsw|fsub|fsubp|fsubr|fsubrp|ftst|fwait|fxam|fxch|fxtract|fyl2x|fyl2xp1)(?-i)\b"
|
||||
color statement "\b(?i)(fsetpm)(?-i)\b"
|
||||
color statement "\b(?i)(fcos|fldenvd|fsaved|fstenvd|fprem1|frstord|fsin|fsincos|fstenvd|fucom|fucomp|fucompp)(?-i)\b"
|
||||
color statement "\b(?i)(fcmovb|fcmovbe|fcmove|fcmove|fcmovnb|fcmovnbe|fcmovne|fcmovnu|fcmovu)(?-i)\b"
|
||||
color statement "\b(?i)(fcomi|fcomip|fucomi|fucomip)(?-i)\b"
|
||||
color statement "\b(?i)(fxrstor|fxsave)(?-i)\b"
|
||||
color statement "\b(?i)(fisttp)(?-i)\b"
|
||||
color statement "\b(?i)(ffreep)(?-i)\b"
|
||||
|
||||
# SIMD
|
||||
color statement "\b(?i)(emms|movd|movq|packssdw|packsswb|packuswb|paddb|paddw|paddd|paddsb|paddsw|paddusb|paddusw|pand|pandn|por|pxor|pcmpeqb|pcmpeqw|pcmpeqd|pcmpgtb|pcmpgtw|pcmpgtd|pmaddwd|pmulhw|pmullw|psllw|pslld|psllq|psrad|psraw|psrlw|psrld|psrlq|psubb|psubw|psubd|psubsb|psubsw|psubusb|punpckhbw|punpckhwd|punpckhdq|punkcklbw|punpckldq|punpcklwd)(?-i)\b"
|
||||
color statement "\b(?i)(paveb|paddsiw|pmagw|pdistib|psubsiw|pmwzb|pmulhrw|pmvnzb|pmvlzb|pmvgezb|pmulhriw|pmachriw)(?-i)\b"
|
||||
color statement "\b(?i)(femms|pavgusb|pf2id|pfacc|pfadd|pfcmpeq|pfcmpge|pfcmpgt|pfmax|pfmin|pfmul|pfrcp|pfrcpit1|pfrcpit2|pfrsqit1|pfrsqrt|pfsub|pfsubr|pi2fd|pmulhrw|prefetch|prefetchw)(?-i)\b"
|
||||
color statement "\b(?i)(pf2iw|pfnacc|pfpnacc|pi2fw|pswapd)(?-i)\b"
|
||||
color statement "\b(?i)(pfrsqrtv|pfrcpv)(?-i)\b"
|
||||
color statement "\b(?i)(addps|addss|cmpps|cmpss|comiss|cvtpi2ps|cvtps2pi|cvtsi2ss|cvtss2si|cvttps2pi|cvttss2si|divps|divss|ldmxcsr|maxps|maxss|minps|minss|movaps|movhlps|movhps|movlhps|movlps|movmskps|movntps|movss|movups|mulps|mulss|rcpps|rcpss|rsqrtps|rsqrtss|shufps|sqrtps|sqrtss|stmxcsr|subps|subss|ucomiss|unpckhps|unpcklps)(?-i)\b"
|
||||
color statement "\b(?i)(andnps|andps|orps|pavgb|pavgw|pextrw|pinsrw|pmaxsw|pmaxub|pminsw|pminub|pmovmskb|pmulhuw|psadbw|pshufw|xorps)(?-i)\b"
|
||||
color statement "\b(?i)(movups|movss|movlps|movhlps|movlps|unpcklps|unpckhps|movhps|movlhps|prefetchnta|prefetch0|prefetch1|prefetch2|nop|movaps|cvtpi2ps|cvtsi2ss|cvtps2pi|cvttss2si|cvtps2pi|cvtss2si|ucomiss|comiss|sqrtps|sqrtss|rsqrtps|rsqrtss|rcpps|andps|orps|xorps|addps|addss|mulps|mulss|subps|subss|minps|minss|divps|divss|maxps|maxss|pshufw|ldmxcsr|stmxcsr|sfence|cmpps|cmpss|pinsrw|pextrw|shufps|pmovmskb|pminub|pmaxub|pavgb|pavgw|pmulhuw|movntq|pminsw|pmaxsw|psadbw|maskmovq)(?-i)\b"
|
||||
color statement "\b(?i)(addpd|addsd|addnpd|cmppd|cmpsd)(?-i)\b"
|
||||
color statement "\b(?i)(addpd|addsd|andnpd|andpd|cmppd|cmpsd|comisd|cvtdq2pd|cvtdq2ps|cvtpd2dq|cvtpd2pi|cvtpd2ps|cvtpi2pd|cvtps2dq|cvtps2pd|cvtsd2si|cvtsd2ss|cvtsi2sd|cvtss2sd|cvttpd2dq|cvttpd2pi|cvttps2dq|cvttsd2si|divpd|divsd|maxpd|maxsd|minpd|minsd|movapd|movhpd|movlpd|movmskpd|movsd|movupd|mulpd|mulsd|orpd|shufpd|sqrtpd|sqrtsd|subpd|subsd|ucomisd|unpckhpd|unpcklpd|xorpd)(?-i)\b"
|
||||
color statement "\b(?i)(movdq2q|movdqa|movdqu|movq2dq|paddq|psubq|pmuludq|pshufhw|pshuflw|pshufd|pslldq|psrldq|punpckhqdq|punpcklqdq)(?-i)\b"
|
||||
color statement "\b(?i)(addsubpd|addsubps|haddpd|haddps|hsubpd|hsubps|movddup|movshdup|movsldu)(?-i)\b"
|
||||
color statement "\b(?i)(lddqu)(?-i)\b"
|
||||
color statement "\b(?i)(psignw|psignd|psignb|pshufb|pmulhrsw|pmaddubsw|phsubw|phsubsw|phsubd|phaddw|phaddsw|phaddd|palignr|pabsw|pabsd|pabsb)(?-i)\b"
|
||||
color statement "\b(?i)(dpps|dppd|blendps|blendpd|blendvps|blendvpd|roundps|roundss|roundpd|roundsd|insertps|extractps)(?-i)\b"
|
||||
color statement "\b(?i)(mpsadbw|phminposuw|pmulld|pmuldq|pblendvb|pblendw|pminsb|pmaxsb|pminuw|pmaxuw|pminud|pmaxud|pminsd|pmaxsd|pinsrb|pinsrd/pinsrq|pextrb|pextrw|pextrd/pextrq|pmovsxbw|pmovzxbw|pmovsxbd|pmovzxbd|pmovsxbq|pmovzxbq|pmovsxwd|pmovzxwd|pmovsxwq|pmovzxwq|pmovsxdq|pmovzxdq|ptest|pcmpeqq|packusdw|movntdqa)(?-i)\b"
|
||||
color statement "\b(?i)(extrq|insertq|movntsd|movntss)(?-i)\b"
|
||||
color statement "\b(?i)(crc32|pcmpestri|pcmpestrm|pcmpistri|pcmpistrm|pcmpgtq)(?-i)\b"
|
||||
color statement "\b(?i)(vfmaddpd|vfmaddps|vfmaddsd|vfmaddss|vfmaddsubpd|vfmaddsubps|vfmsubaddpd|vfmsubaddps|vfmsubpd|vfmsubps|vfmsubsd|vfmsubss|vfnmaddpd|vfnmaddps|vfnmaddsd|vfnmaddss|vfnmsubps|vfnmsubsd|vfnmsubss)(?-i)\b"
|
||||
|
||||
# Crypto
|
||||
color statement "\b(?i)(aesenc|aesenclast|aesdec|aesdeclast|aeskeygenassist|aesimc)(?-i)\b"
|
||||
color statement "\b(?i)(sha1rnds4|sha1nexte|sha1msg1|sha1msg2|sha256rnds2|sha256msg1|sha256msg2)(?-i)\b"
|
||||
|
||||
# Undocumented
|
||||
color statement "\b(?i)(aam|aad|salc|icebp|loadall|loadalld|ud1)(?-i)\b"
|
||||
|
||||
## Registers
|
||||
color identifier "\b(?i)(al|ah|bl|bh|cl|ch|dl|dh|bpl|sil|r8b|r9b|r10b|r11b|dil|spl|r12b|r13b|r14b|r15)(?-i)\b"
|
||||
color identifier "\b(?i)(cw|sw|tw|fp_ds|fp_opc|fp_ip|fp_dp|fp_cs|cs|ss|ds|es|fs|gs|gdtr|idtr|tr|ldtr|ax|bx|cx|dx|bp|si|r8w|r9w|r10w|r11w|di|sp|r12w|r13w|r14w|r15w|ip)(?-i)\b"
|
||||
color identifier "\b(?i)(fp_dp|fp_ip|eax|ebx|ecx|edx|ebp|esi|r8d|r9d|r10d|r11d|edi|esp|r12d|r13d|r14d|r15d|eip|eflags|mxcsr)(?-i)\b"
|
||||
color identifier "\b(?i)(mm0|mm1|mm2|mm3|mm4|mm5|mm6|mm7|rax|rbx|rcx|rdx|rbp|rsi|r8|r9|r10|r11|rdi|rsp|r12|r13|r14|r15|rip|rflags|cr0|cr1|cr2|cr3|cr4|cr5|cr6|cr7|cr8|cr9|cr10|cr11|cr12|cr13|cr14|cr15|msw|dr0|dr1|dr2|dr3|r4|dr5|dr6|dr7|dr8|dr9|dr10|dr11|dr12|dr13|dr14|dr15)(?-i)\b"
|
||||
color identifier "\b(?i)(st0|st1|st2|st3|st4|st5|st6|st7)(?-i)\b"
|
||||
color identifier "\b(?i)(xmm0|xmm1|xmm2|xmm3|xmm4|xmm5|xmm6|xmm7|xmm8|xmm9|xmm10|xmm11|xmm12|xmm13|xmm14|xmm15)(?-i)\b"
|
||||
color identifier "\b(?i)(ymm0|ymm1|ymm2|ymm3|ymm4|ymm5|ymm6|ymm7|ymm8|ymm9|ymm10|ymm11|ymm12|ymm13|ymm14|ymm15)(?-i)\b"
|
||||
color identifier "\b(?i)(zmm0|zmm1|zmm2|zmm3|zmm4|zmm5|zmm6|zmm7|zmm8|zmm9|zmm10|zmm11|zmm12|zmm13|zmm14|zmm15|zmm16|zmm17|zmm18|zmm19|zmm20|zmm21|zmm22|zmm23|zmm24|zmm25|zmm26|zmm27|zmm28|zmm29|zmm30|zmm31)(?-i)\b"
|
||||
|
||||
## Constants
|
||||
# Number - it works
|
||||
color constant.number "\b(|h|A|0x)+[0-9]+(|h|A)+\b"
|
||||
color constant.number "\b0x[0-9 a-f A-F]+\b"
|
||||
|
||||
## Preprocessor (NASM)
|
||||
color preproc "%+(\+|\?|\?\?|)[a-z A-Z 0-9]+"
|
||||
color preproc "%\[[. a-z A-Z 0-9]*\]"
|
||||
|
||||
## Other
|
||||
color statement "\b(?i)(extern|global|section|segment|_start|\.text|\.data|\.bss)(?-i)\b"
|
||||
color statement "\b(?i)(db|dw|dd|dq|dt|ddq|do)(?-i)\b"
|
||||
color identifier "[a-z A-Z 0-9 _]+:"
|
||||
|
||||
# String
|
||||
color constant.string ""(\\.|[^"])*""
|
||||
color constant.string "'(\\.|[^'])*'"
|
||||
|
||||
## Comments
|
||||
color comment ";.*"
|
||||
110
runtime/syntax/asm.yaml
Normal file
110
runtime/syntax/asm.yaml
Normal file
@@ -0,0 +1,110 @@
|
||||
filetype: asm
|
||||
|
||||
detect:
|
||||
filename: "\\.(S|s|asm)$"
|
||||
|
||||
rules:
|
||||
# This file is made for NASM assembly
|
||||
|
||||
## Instructions
|
||||
# x86
|
||||
- statement: "\\b(?i)(mov|aaa|aad|aam|aas|adc|add|and|call|cbw|clc|cld|cli|cmc|cmp|cmpsb|cmpsw|cwd|daa|das|dec|div|esc|hlt|idiv|imul|in|inc|int|into|iret|ja|jae|jb|jbe|jc|je|jg|jge|jl|jle|jna|jnae|jnb|jnbe|jnc|jne|jng|jnge|jnl|jnle|jno|jnp|jns|jnz|jo|jp|jpe|jpo|js|jz|jcxz|jmp|lahf|lds|lea|les|lock|lodsb|lodsw|loop|loope|loopne|loopnz|loopz|movsb|movsw|mul|neg|nop|or|pop|popf|push|pushf|rcl|rcr|rep|repe|repne|repnz|repz|ret|retn|retf|rol|ror|sahf|sal|sar|sbb|scasb|scasw|shl|shr|stc|std|sti|stosb|stosw|sub|test|wait|xchg|xlat|xor)(?-i)\\b"
|
||||
- statement: "\\b(?i)(bound|enter|ins|leave|outs|popa|pusha)(?-i)\\b"
|
||||
- statement: "\\b(?i)(arpl|clts|lar|lgdt|lidt|lldt|lmsw|loadall|lsl|ltr|sgdt|sidt|sldt|smsw|str|verr|verw)(?-i)\\b"
|
||||
- statement: "\\b(?i)(bsf|bsr|bt|btc|btr|bts|cdq|cmpsd|cwde|insd|iret|iretd|iretf|jecxz|lfs|lgs|lss|lodsd|loopw|loopew|loopnew|loopnzw|loopzw|loopd|looped|loopned|loopnzd|loopzd|cr|tr|dr|movsd|movsx|movzx|outsd|popad|popfd|pushad|pushfd|scasd|seta|setae|setb|setbe|setc|sete|setg|setge|setl|setle|setna|setnae|setnb|setnbe|setnc|setne|setng|setnge|setnl|setnle|setno|setnp|setns|setnz|seto|setp|setpe|setpo|sets|setz|shdl|shrd|stosd)(?-i)\\b"
|
||||
- statement: "\\b(?i)(bswap|cmpxcgh|invd|invlpg|wbinvd|xadd)(?-i)\\b"
|
||||
- statement: "\\b(?i)(cpuid|cmpxchg8b|rdmsr|rdtsc|wrmsr|rsm)(?-i)\\b"
|
||||
- statement: "\\b(?i)(rdpmc)(?-i)\\b"
|
||||
- statement: "\\b(?i)(syscall|sysret)(?-i)\\b"
|
||||
- statement: "\\b(?i)(cmova|cmovae|cmovb|cmovbe|cmovc|cmove|cmovg|cmovge|cmovl|cmovle|cmovna|cmovnae|cmovnb|cmovnbe|cmovnc|cmovne|cmovng|cmovnge|cmovnle|cmovno|cmovpn|cmovns|cmovnz|cmovo|cmovp|cmovpe|cmovpo|cmovs|cmovz|sysenter|sysexit|ud2)(?-i)\\b"
|
||||
- statement: "\\b(?i)(maskmovq|movntps|movntq|prefetch0|prefetch1|prefetch2|prefetchnta|sfence)(?-i)\\b"
|
||||
- statement: "\\b(?i)(clflush|lfence|maskmovdqu|mfence|movntdq|movnti|movntpd|pause)(?-i)\\b"
|
||||
- statement: "\\b(?i)(monitor|mwait)(?-i)\\b"
|
||||
- statement: "\\b(?i)(cdqe|cqo|cmpsq|cmpxchg16b|iretq|jrcxz|lodsq|movsdx|popfq|pushfq|rdtscp|scasq|stosq|swapgs)(?-i)\\b"
|
||||
- statement: "\\b(?i)(clgi|invlpga|skinit|stgi|vmload|vmmcall|vmrun|vmsave)(?-i)\\b"
|
||||
- statement: "\\b(?i)(vmptrdl|vmptrst|vmclear|vmread|vmwrite|vmcall|vmlaunch|vmresume|vmxoff|vmxon)(?-i)\\b"
|
||||
- statement: "\\b(?i)(lzcnt|popcnt)(?-i)\\b"
|
||||
- statement: "\\b(?i)(bextr|blcfill|blci|blcic|blcmask|blcs|blsfill|blsic|t1mskc|tzmsk)(?-i)\\b"
|
||||
|
||||
# x87
|
||||
- statement: "\\b(?i)(f2xm1|fabs|fadd|faddp|fbld|fbstp|fchs|fclex|fcom|fcomp|fcompp|fdecstp|fdisi|fdiv|fvidp|fdivr|fdivrp|feni|ffree|fiadd|ficom|ficomp|fidiv|fidivr|fild|fimul|fincstp|finit|fist|fistp|fisub|fisubr|fld|fld1|fldcw|fldenv|fldenvw|fldl2e|fldl2t|fldlg2|fldln2|fldpi|fldz|fmul|fmulp|fnclex|fndisi|fneni|fninit|fnop|fnsave|fnsavenew|fnstcw|fnstenv|fnstenvw|fnstsw|fpatan|fprem|fptan|frndint|frstor|frstorw|fsave|fsavew|fscale|fsqrt|fst|fstcw|fstenv|fstenvw|fstp|fstpsw|fsub|fsubp|fsubr|fsubrp|ftst|fwait|fxam|fxch|fxtract|fyl2x|fyl2xp1)(?-i)\\b"
|
||||
- statement: "\\b(?i)(fsetpm)(?-i)\\b"
|
||||
- statement: "\\b(?i)(fcos|fldenvd|fsaved|fstenvd|fprem1|frstord|fsin|fsincos|fstenvd|fucom|fucomp|fucompp)(?-i)\\b"
|
||||
- statement: "\\b(?i)(fcmovb|fcmovbe|fcmove|fcmove|fcmovnb|fcmovnbe|fcmovne|fcmovnu|fcmovu)(?-i)\\b"
|
||||
- statement: "\\b(?i)(fcomi|fcomip|fucomi|fucomip)(?-i)\\b"
|
||||
- statement: "\\b(?i)(fxrstor|fxsave)(?-i)\\b"
|
||||
- statement: "\\b(?i)(fisttp)(?-i)\\b"
|
||||
- statement: "\\b(?i)(ffreep)(?-i)\\b"
|
||||
|
||||
# SIMD
|
||||
- statement: "\\b(?i)(emms|movd|movq|packssdw|packsswb|packuswb|paddb|paddw|paddd|paddsb|paddsw|paddusb|paddusw|pand|pandn|por|pxor|pcmpeqb|pcmpeqw|pcmpeqd|pcmpgtb|pcmpgtw|pcmpgtd|pmaddwd|pmulhw|pmullw|psllw|pslld|psllq|psrad|psraw|psrlw|psrld|psrlq|psubb|psubw|psubd|psubsb|psubsw|psubusb|punpckhbw|punpckhwd|punpckhdq|punkcklbw|punpckldq|punpcklwd)(?-i)\\b"
|
||||
- statement: "\\b(?i)(paveb|paddsiw|pmagw|pdistib|psubsiw|pmwzb|pmulhrw|pmvnzb|pmvlzb|pmvgezb|pmulhriw|pmachriw)(?-i)\\b"
|
||||
- statement: "\\b(?i)(femms|pavgusb|pf2id|pfacc|pfadd|pfcmpeq|pfcmpge|pfcmpgt|pfmax|pfmin|pfmul|pfrcp|pfrcpit1|pfrcpit2|pfrsqit1|pfrsqrt|pfsub|pfsubr|pi2fd|pmulhrw|prefetch|prefetchw)(?-i)\\b"
|
||||
- statement: "\\b(?i)(pf2iw|pfnacc|pfpnacc|pi2fw|pswapd)(?-i)\\b"
|
||||
- statement: "\\b(?i)(pfrsqrtv|pfrcpv)(?-i)\\b"
|
||||
- statement: "\\b(?i)(addps|addss|cmpps|cmpss|comiss|cvtpi2ps|cvtps2pi|cvtsi2ss|cvtss2si|cvttps2pi|cvttss2si|divps|divss|ldmxcsr|maxps|maxss|minps|minss|movaps|movhlps|movhps|movlhps|movlps|movmskps|movntps|movss|movups|mulps|mulss|rcpps|rcpss|rsqrtps|rsqrtss|shufps|sqrtps|sqrtss|stmxcsr|subps|subss|ucomiss|unpckhps|unpcklps)(?-i)\\b"
|
||||
- statement: "\\b(?i)(andnps|andps|orps|pavgb|pavgw|pextrw|pinsrw|pmaxsw|pmaxub|pminsw|pminub|pmovmskb|pmulhuw|psadbw|pshufw|xorps)(?-i)\\b"
|
||||
- statement: "\\b(?i)(movups|movss|movlps|movhlps|movlps|unpcklps|unpckhps|movhps|movlhps|prefetchnta|prefetch0|prefetch1|prefetch2|nop|movaps|cvtpi2ps|cvtsi2ss|cvtps2pi|cvttss2si|cvtps2pi|cvtss2si|ucomiss|comiss|sqrtps|sqrtss|rsqrtps|rsqrtss|rcpps|andps|orps|xorps|addps|addss|mulps|mulss|subps|subss|minps|minss|divps|divss|maxps|maxss|pshufw|ldmxcsr|stmxcsr|sfence|cmpps|cmpss|pinsrw|pextrw|shufps|pmovmskb|pminub|pmaxub|pavgb|pavgw|pmulhuw|movntq|pminsw|pmaxsw|psadbw|maskmovq)(?-i)\\b"
|
||||
- statement: "\\b(?i)(addpd|addsd|addnpd|cmppd|cmpsd)(?-i)\\b"
|
||||
- statement: "\\b(?i)(addpd|addsd|andnpd|andpd|cmppd|cmpsd|comisd|cvtdq2pd|cvtdq2ps|cvtpd2dq|cvtpd2pi|cvtpd2ps|cvtpi2pd|cvtps2dq|cvtps2pd|cvtsd2si|cvtsd2ss|cvtsi2sd|cvtss2sd|cvttpd2dq|cvttpd2pi|cvttps2dq|cvttsd2si|divpd|divsd|maxpd|maxsd|minpd|minsd|movapd|movhpd|movlpd|movmskpd|movsd|movupd|mulpd|mulsd|orpd|shufpd|sqrtpd|sqrtsd|subpd|subsd|ucomisd|unpckhpd|unpcklpd|xorpd)(?-i)\\b"
|
||||
- statement: "\\b(?i)(movdq2q|movdqa|movdqu|movq2dq|paddq|psubq|pmuludq|pshufhw|pshuflw|pshufd|pslldq|psrldq|punpckhqdq|punpcklqdq)(?-i)\\b"
|
||||
- statement: "\\b(?i)(addsubpd|addsubps|haddpd|haddps|hsubpd|hsubps|movddup|movshdup|movsldu)(?-i)\\b"
|
||||
- statement: "\\b(?i)(lddqu)(?-i)\\b"
|
||||
- statement: "\\b(?i)(psignw|psignd|psignb|pshufb|pmulhrsw|pmaddubsw|phsubw|phsubsw|phsubd|phaddw|phaddsw|phaddd|palignr|pabsw|pabsd|pabsb)(?-i)\\b"
|
||||
- statement: "\\b(?i)(dpps|dppd|blendps|blendpd|blendvps|blendvpd|roundps|roundss|roundpd|roundsd|insertps|extractps)(?-i)\\b"
|
||||
- statement: "\\b(?i)(mpsadbw|phminposuw|pmulld|pmuldq|pblendvb|pblendw|pminsb|pmaxsb|pminuw|pmaxuw|pminud|pmaxud|pminsd|pmaxsd|pinsrb|pinsrd/pinsrq|pextrb|pextrw|pextrd/pextrq|pmovsxbw|pmovzxbw|pmovsxbd|pmovzxbd|pmovsxbq|pmovzxbq|pmovsxwd|pmovzxwd|pmovsxwq|pmovzxwq|pmovsxdq|pmovzxdq|ptest|pcmpeqq|packusdw|movntdqa)(?-i)\\b"
|
||||
- statement: "\\b(?i)(extrq|insertq|movntsd|movntss)(?-i)\\b"
|
||||
- statement: "\\b(?i)(crc32|pcmpestri|pcmpestrm|pcmpistri|pcmpistrm|pcmpgtq)(?-i)\\b"
|
||||
- statement: "\\b(?i)(vfmaddpd|vfmaddps|vfmaddsd|vfmaddss|vfmaddsubpd|vfmaddsubps|vfmsubaddpd|vfmsubaddps|vfmsubpd|vfmsubps|vfmsubsd|vfmsubss|vfnmaddpd|vfnmaddps|vfnmaddsd|vfnmaddss|vfnmsubps|vfnmsubsd|vfnmsubss)(?-i)\\b"
|
||||
|
||||
# Crypto
|
||||
- statement: "\\b(?i)(aesenc|aesenclast|aesdec|aesdeclast|aeskeygenassist|aesimc)(?-i)\\b"
|
||||
- statement: "\\b(?i)(sha1rnds4|sha1nexte|sha1msg1|sha1msg2|sha256rnds2|sha256msg1|sha256msg2)(?-i)\\b"
|
||||
|
||||
# Undocumented
|
||||
- statement: "\\b(?i)(aam|aad|salc|icebp|loadall|loadalld|ud1)(?-i)\\b"
|
||||
|
||||
## Registers
|
||||
- identifier: "\\b(?i)(al|ah|bl|bh|cl|ch|dl|dh|bpl|sil|r8b|r9b|r10b|r11b|dil|spl|r12b|r13b|r14b|r15)(?-i)\\b"
|
||||
- identifier: "\\b(?i)(cw|sw|tw|fp_ds|fp_opc|fp_ip|fp_dp|fp_cs|cs|ss|ds|es|fs|gs|gdtr|idtr|tr|ldtr|ax|bx|cx|dx|bp|si|r8w|r9w|r10w|r11w|di|sp|r12w|r13w|r14w|r15w|ip)(?-i)\\b"
|
||||
- identifier: "\\b(?i)(fp_dp|fp_ip|eax|ebx|ecx|edx|ebp|esi|r8d|r9d|r10d|r11d|edi|esp|r12d|r13d|r14d|r15d|eip|eflags|mxcsr)(?-i)\\b"
|
||||
- identifier: "\\b(?i)(mm0|mm1|mm2|mm3|mm4|mm5|mm6|mm7|rax|rbx|rcx|rdx|rbp|rsi|r8|r9|r10|r11|rdi|rsp|r12|r13|r14|r15|rip|rflags|cr0|cr1|cr2|cr3|cr4|cr5|cr6|cr7|cr8|cr9|cr10|cr11|cr12|cr13|cr14|cr15|msw|dr0|dr1|dr2|dr3|r4|dr5|dr6|dr7|dr8|dr9|dr10|dr11|dr12|dr13|dr14|dr15)(?-i)\\b"
|
||||
- identifier: "\\b(?i)(st0|st1|st2|st3|st4|st5|st6|st7)(?-i)\\b"
|
||||
- identifier: "\\b(?i)(xmm0|xmm1|xmm2|xmm3|xmm4|xmm5|xmm6|xmm7|xmm8|xmm9|xmm10|xmm11|xmm12|xmm13|xmm14|xmm15)(?-i)\\b"
|
||||
- identifier: "\\b(?i)(ymm0|ymm1|ymm2|ymm3|ymm4|ymm5|ymm6|ymm7|ymm8|ymm9|ymm10|ymm11|ymm12|ymm13|ymm14|ymm15)(?-i)\\b"
|
||||
- identifier: "\\b(?i)(zmm0|zmm1|zmm2|zmm3|zmm4|zmm5|zmm6|zmm7|zmm8|zmm9|zmm10|zmm11|zmm12|zmm13|zmm14|zmm15|zmm16|zmm17|zmm18|zmm19|zmm20|zmm21|zmm22|zmm23|zmm24|zmm25|zmm26|zmm27|zmm28|zmm29|zmm30|zmm31)(?-i)\\b"
|
||||
|
||||
## Constants
|
||||
# Number - it works
|
||||
- constant.number: "\\b(|h|A|0x)+[0-9]+(|h|A)+\\b"
|
||||
- constant.number: "\\b0x[0-9 a-f A-F]+\\b"
|
||||
|
||||
## Preprocessor (NASM)
|
||||
- preproc: "%+(\\+|\\?|\\?\\?|)[a-z A-Z 0-9]+"
|
||||
- preproc: "%\\[[. a-z A-Z 0-9]*\\]"
|
||||
|
||||
## Other
|
||||
- statement: "\\b(?i)(extern|global|section|segment|_start|\\.text|\\.data|\\.bss)(?-i)\\b"
|
||||
- statement: "\\b(?i)(db|dw|dd|dq|dt|ddq|do)(?-i)\\b"
|
||||
- identifier: "[a-z A-Z 0-9 _]+:"
|
||||
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- constant.string:
|
||||
start: "'"
|
||||
end: "'"
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- comment:
|
||||
start: ";"
|
||||
end: "$"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
syntax "awk" "\.awk$"
|
||||
header "^#!.*bin/(env +)?awk( |$)"
|
||||
|
||||
color brightyellow "\$[A-Za-z0-9_!@#$*?-]+"
|
||||
color brightyellow "\<(ARGC|ARGIND|ARGV|BINMODE|CONVFMT|ENVIRON|ERRNO|FIELDWIDTHS)\>"
|
||||
color brightyellow "\<(FILENAME|FNR|FS|IGNORECASE|LINT|NF|NR|OFMT|OFS|ORS)\>"
|
||||
color brightyellow "\<(PROCINFO|RS|RT|RSTART|RLENGTH|SUBSEP|TEXTDOMAIN)\>"
|
||||
color brightblue "\<(function|extension|BEGIN|END)\>"
|
||||
color red "[-+*/%^|!=&<>?;:]|\\|\[|\]"
|
||||
color cyan "\<(for|if|while|do|else|in|delete|exit)\>"
|
||||
color cyan "\<(break|continue|return)\>"
|
||||
color brightblue "\<(close|getline|next|nextfile|print|printf|system|fflush)\>"
|
||||
color brightblue "\<(atan2|cos|exp|int|log|rand|sin|sqrt|srand)\>"
|
||||
color brightblue "\<(asort|asorti|gensub|gsub|index|length|match)\>"
|
||||
color brightblue "\<(split|sprintf|strtonum|sub|substr|tolower|toupper)\>"
|
||||
color brightblue "\<(mktime|strftime|systime)\>"
|
||||
color brightblue "\<(and|compl|lshift|or|rshift|xor)\>"
|
||||
color brightblue "\<(bindtextdomain|dcgettext|dcngettext)\>"
|
||||
color magenta "/.*[^\\]/"
|
||||
color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'"
|
||||
color magenta "\\."
|
||||
color brightblack "(^|[[:space:]])#([^{].*)?$"
|
||||
color brightwhite,cyan "TODO:?"
|
||||
color ,green "[[:space:]]+$"
|
||||
color ,red " + +| + +"
|
||||
44
runtime/syntax/awk.yaml
Normal file
44
runtime/syntax/awk.yaml
Normal file
@@ -0,0 +1,44 @@
|
||||
filetype: awk
|
||||
|
||||
detect:
|
||||
filename: "\\.awk$"
|
||||
header: "^#!.*bin/(env +)?awk( |$)"
|
||||
|
||||
rules:
|
||||
- preproc: "\\$[A-Za-z0-9_!@#$*?\\-]+"
|
||||
- preproc: "\\b(ARGC|ARGIND|ARGV|BINMODE|CONVFMT|ENVIRON|ERRNO|FIELDWIDTHS)\\b"
|
||||
- preproc: "\\b(FILENAME|FNR|FS|IGNORECASE|LINT|NF|NR|OFMT|OFS|ORS)\\b"
|
||||
- preproc: "\\b(PROCINFO|RS|RT|RSTART|RLENGTH|SUBSEP|TEXTDOMAIN)\\b"
|
||||
- identifier.class: "\\b(function|extension|BEGIN|END)\\b"
|
||||
- symbol.operator: "[\\-+*/%^|!=&<>?;:]|\\\\|\\[|\\]"
|
||||
- statement: "\\b(for|if|while|do|else|in|delete|exit)\\b"
|
||||
- special: "\\b(break|continue|return)\\b"
|
||||
- statement: "\\b(close|getline|next|nextfile|print|printf|system|fflush)\\b"
|
||||
- statement: "\\b(atan2|cos|exp|int|log|rand|sin|sqrt|srand)\\b"
|
||||
- statement: "\\b(asort|asorti|gensub|gsub|index|length|match)\\b"
|
||||
- statement: "\\b(split|sprintf|strtonum|sub|substr|tolower|toupper)\\b"
|
||||
- statement: "\\b(mktime|strftime|systime)\\b"
|
||||
- statement: "\\b(and|compl|lshift|or|rshift|xor)\\b"
|
||||
- statement: "\\b(bindtextdomain|dcgettext|dcngettext)\\b"
|
||||
- special: "/.*[^\\\\]/"
|
||||
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- constant.string:
|
||||
start: "'"
|
||||
end: "'"
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- comment:
|
||||
start: "#"
|
||||
end: "$"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
|
||||
28
runtime/syntax/c++.yaml
Normal file
28
runtime/syntax/c++.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
filetype: c++
|
||||
|
||||
detect:
|
||||
filename: "\\.c(c|pp|xx)$|\\.h(h|pp|xx)$|\\.ii?$|\\.(def)$"
|
||||
|
||||
rules:
|
||||
- identifier: "\\b[A-Z_][0-9A-Z_]+\\b"
|
||||
- type: "\\b(auto|float|double|bool|char|int|short|long|sizeof|enum|void|static|const|constexpr|struct|union|typedef|extern|(un)?signed|inline)\\b"
|
||||
- type: "\\b((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\\b"
|
||||
- statement: "\\b(class|namespace|template|public|protected|private|typename|this|friend|virtual|using|mutable|volatile|register|explicit)\\b"
|
||||
- statement: "\\b(for|if|while|do|else|case|default|switch)\\b"
|
||||
- statement: "\\b(try|throw|catch|operator|new|delete)\\b"
|
||||
- special: "\\b(goto|continue|break|return)\\b"
|
||||
- preproc: "^[[:space:]]*#[[:space:]]*(define|pragma|include|(un|ifn?)def|endif|el(if|se)|if|warning|error)"
|
||||
- constant: "'([^'\\\\]|(\\\\[\"'abfnrtv\\\\]))'|'\\\\(([0-3]?[0-7]{1,2}))'|'\\\\x[0-9A-Fa-f]{1,2}'"
|
||||
- statement: "__attribute__[[:space:]]*\\(\\([^)]*\\)\\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||
- symbol.operator: "[.:;,+*|=!\\%]|<|>|/|-|&"
|
||||
- symbol.brackets: "[(){}]|\\[|\\]"
|
||||
- constant.number: "\\b[0-9]+\\b|\\b0x[0-9A-Fa-f]+\\b"
|
||||
- constant.bool: "\\b(true|false)\\b|NULL"
|
||||
- constant.string: "\"(\\\\.|[^\"])*\""
|
||||
- comment: "//.*"
|
||||
- comment:
|
||||
start: "/\\*"
|
||||
end: "\\*/"
|
||||
rules: []
|
||||
|
||||
- indent-char.whitespace: "[[:space:]]+$"
|
||||
@@ -1,40 +0,0 @@
|
||||
## Here is an example for C/C++.
|
||||
##
|
||||
syntax "c" "\.(c(c|pp|xx)?|C)$" "\.(h(h|pp|xx)?|H)$" "\.ii?$" "\.(def)$"
|
||||
color identifier "\b[A-Z_][0-9A-Z_]+\b"
|
||||
color type "\b(float|double|bool|char|int|short|long|sizeof|enum|void|static|const|struct|union|typedef|extern|(un)?signed|inline)\b"
|
||||
color type "\b((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\b"
|
||||
color statement "\b(class|namespace|template|public|protected|private|typename|this|friend|virtual|using|mutable|volatile|register|explicit)\b"
|
||||
color statement "\b(for|if|while|do|else|case|default|switch)\b"
|
||||
color statement "\b(try|throw|catch|operator|new|delete)\b"
|
||||
color statement "\b(goto|continue|break|return)\b"
|
||||
color preproc "^[[:space:]]*#[[:space:]]*(define|include|(un|ifn?)def|endif|el(if|se)|if|warning|error)"
|
||||
color constant "'([^'\\]|(\\["'abfnrtv\\]))'" "'\\(([0-3]?[0-7]{1,2}))'" "'\\x[0-9A-Fa-f]{1,2}'"
|
||||
|
||||
##
|
||||
## GCC builtins
|
||||
color statement "__attribute__[[:space:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||
|
||||
#Operator Color
|
||||
color statement "[.:;,+*|=!\%]" "<" ">" "/" "-" "&"
|
||||
|
||||
#Parenthetical Color
|
||||
# color magenta "[(){}]" "\[" "\]"
|
||||
|
||||
color constant.number "\b[0-9]+\b" "\b0x[0-9A-Fa-f]+\b"
|
||||
|
||||
##
|
||||
## String highlighting. You will in general want your brightblacks and
|
||||
## strings to come last, because syntax highlighting rules will be
|
||||
## applied in the order they are read in.
|
||||
color constant.string ""(\\.|[^"])*""
|
||||
##
|
||||
## This string is VERY resource intensive!
|
||||
#color cyan start=""(\\.|[^"])*\\[[:space:]]*$" end="^(\\.|[^"])*""
|
||||
|
||||
## Comment highlighting
|
||||
color comment "//.*"
|
||||
color comment start="/\*" end="\*/"
|
||||
|
||||
## Trailing whitespace
|
||||
#color ,green "[[:space:]]+$"
|
||||
54
runtime/syntax/c.yaml
Normal file
54
runtime/syntax/c.yaml
Normal file
@@ -0,0 +1,54 @@
|
||||
filetype: c
|
||||
|
||||
detect:
|
||||
filename: "(\\.(c|C)$|\\.(h|H)$|\\.ii?$|\\.(def)$)"
|
||||
|
||||
rules:
|
||||
- identifier: "\\b[A-Z_][0-9A-Z_]+\\b"
|
||||
- type: "\\b(float|double|char|int|short|long|sizeof|enum|void|static|const|struct|union|typedef|extern|(un)?signed|inline)\\b"
|
||||
- type: "\\b((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\\b"
|
||||
- type.extended: "\\b(bool)\\b"
|
||||
- statement: "\\b(typename|mutable|volatile|register|explicit)\\b"
|
||||
- statement: "\\b(for|if|while|do|else|case|default|switch)\\b"
|
||||
- statement: "\\b(try|throw|catch|operator|new|delete)\\b"
|
||||
- statement: "\\b(goto|continue|break|return)\\b"
|
||||
- preproc: "^[[:space:]]*#[[:space:]]*(define|pragma|include|(un|ifn?)def|endif|el(if|se)|if|warning|error)"
|
||||
- constant: "'([^'\\\\]|(\\\\[\"'abfnrtv\\\\]))'"
|
||||
- constant: "'\\\\(([0-3]?[0-7]{1,2}))'"
|
||||
- constant: "'\\\\x[0-9A-Fa-f]{1,2}'"
|
||||
# GCC builtins
|
||||
- statement: "__attribute__[[:space:]]*\\(\\([^)]*\\)\\)"
|
||||
- statement: "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||
# Operator Color
|
||||
- symbol.operator: "([.:;,+*|=!\\%]|<|>|/|-|&)"
|
||||
- symbol.brackets: "[(){}]|\\[|\\]"
|
||||
- constant.number: "(\\b[0-9]+\\b|\\b0x[0-9A-Fa-f]+\\b)"
|
||||
- constant.number: "NULL"
|
||||
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- constant.string:
|
||||
start: "'"
|
||||
end: "'"
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- preproc: "..+"
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- comment:
|
||||
start: "//"
|
||||
end: "$"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
|
||||
- comment:
|
||||
start: "/\\*"
|
||||
end: "\\*/"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
syntax "caddyfile" "Caddyfile"
|
||||
|
||||
color identifier "^\s*\S+(\s|$)"
|
||||
color type "^([\w.:/-]+,? ?)+[,{]$"
|
||||
color constant.specialChar "\s{$"
|
||||
color constant.specialChar "^\s*}$"
|
||||
color constant.string start="\"" end="\""
|
||||
color preproc "\{(\w+|\$\w+|%\w+%)\}"
|
||||
color comment "#.*"
|
||||
|
||||
# extra and trailing spaces
|
||||
color ,red "([[:space:]]{2,}|\t){$"
|
||||
color ,red "[[:space:]]+$"
|
||||
23
runtime/syntax/caddyfile.yaml
Normal file
23
runtime/syntax/caddyfile.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
filetype: caddyfile
|
||||
|
||||
detect:
|
||||
filename: "Caddyfile"
|
||||
|
||||
rules:
|
||||
- identifier: "^\\s*\\S+(\\s|$)"
|
||||
- type: "^([\\w.:/-]+,? ?)+[,{]$"
|
||||
- constant.specialChar: "\\s{$"
|
||||
- constant.specialChar: "^\\s*}$"
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- preproc: "\\{(\\w+|\\$\\w+|%\\w+%)\\}"
|
||||
- comment:
|
||||
start: "#"
|
||||
end: "$"
|
||||
rules: []
|
||||
|
||||
38
runtime/syntax/clojure.yaml
Normal file
38
runtime/syntax/clojure.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
filetype: clojure
|
||||
|
||||
detect:
|
||||
filename: "\\.(clj)$"
|
||||
|
||||
rules:
|
||||
|
||||
# Constants
|
||||
- constant.bool: "\\b(true|false)\\b"
|
||||
- constant.macro: "\\b(nil)\\b"
|
||||
# Valid numbers
|
||||
- constant.number: "[\\-]?[0-9]+?\\b"
|
||||
- constant.number: "0x[0-9][A-Fa-f]+?\\b"
|
||||
- constant.number: "[\\-]?(3[0-6]|2[0-9]|1[0-9]|[2-9])r[0-9A-Z]+?\\b"
|
||||
# Invalid numbers
|
||||
- error: "[\\-]?([4-9][0-9]|3[7-9]|1|0)r[0-9A-Z]+?\\b"
|
||||
|
||||
# Symbols
|
||||
- symbol.operator: "[=>+\\-*/'?]"
|
||||
|
||||
# Types/casting
|
||||
- type: "\\b(byte|short|(big)?int(eger)?|long|float|num|bigdec|rationalize)\\b"
|
||||
|
||||
# String highlighting
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "(\\\\u[0-9A-fa-f]{4,4}|\\\\newline|\\\\space|\\\\tab|\\\\formfeed|\\\\backspace|\\\\return|\\\\.)"
|
||||
|
||||
# Comments
|
||||
- comment:
|
||||
start: ";"
|
||||
end: "$"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
## CMake syntax highlighter for GNU Nano
|
||||
##
|
||||
syntax "cmake" "(CMakeLists\.txt|\.cmake)$"
|
||||
|
||||
green (i) "^[[:space:]]*[A-Z0-9_]+"
|
||||
brightyellow (i) "^[[:space:]]*(include|include_directories|include_external_msproject)\>"
|
||||
|
||||
brightgreen (i) "^[[:space:]]*\<((else|end)?if|else|(end)?while|(end)?foreach|break)\>"
|
||||
color brightgreen "\<(COPY|NOT|COMMAND|PROPERTY|POLICY|TARGET|EXISTS|IS_(DIRECTORY|ABSOLUTE)|DEFINED)\>[[:space:]]"
|
||||
color brightgreen "[[:space:]]\<(OR|AND|IS_NEWER_THAN|MATCHES|(STR|VERSION_)?(LESS|GREATER|EQUAL))\>[[:space:]]"
|
||||
|
||||
brightred (i) "^[[:space:]]*\<((end)?(function|macro)|return)"
|
||||
|
||||
#String Color
|
||||
color cyan "['][^']*[^\\][']" "[']{3}.*[^\\][']{3}"
|
||||
color cyan "["][^"]*[^\\]["]" "["]{3}.*[^\\]["]{3}"
|
||||
|
||||
brightred (i) start="\$(\{|ENV\{)" end="\}"
|
||||
color magenta "\<(APPLE|UNIX|WIN32|CYGWIN|BORLAND|MINGW|MSVC(_IDE|60|71|80|90)?)\>"
|
||||
|
||||
brightblue (i) "^([[:space:]]*)?#.*"
|
||||
brightblue (i) "[[:space:]]#.*"
|
||||
|
||||
42
runtime/syntax/cmake.yaml
Normal file
42
runtime/syntax/cmake.yaml
Normal file
@@ -0,0 +1,42 @@
|
||||
filetype: cmake
|
||||
|
||||
detect:
|
||||
filename: "(CMakeLists\\.txt|\\.cmake)$"
|
||||
|
||||
rules:
|
||||
- identifier.var: "^[[:space:]]*[A-Z0-9_]+"
|
||||
- preproc: "^[[:space:]]*(include|include_directories|include_external_msproject)\\b"
|
||||
|
||||
- statement: "^[[:space:]]*\\b((else|end)?if|else|(end)?while|(end)?foreach|break)\\b"
|
||||
- statement: "\\b(COPY|NOT|COMMAND|PROPERTY|POLICY|TARGET|EXISTS|IS_(DIRECTORY|ABSOLUTE)|DEFINED)\\b[[:space:]]"
|
||||
- statement: "[[:space:]]\\b(OR|AND|IS_NEWER_THAN|MATCHES|(STR|VERSION_)?(LESS|GREATER|EQUAL))\\b[[:space:]]"
|
||||
|
||||
- special: "^[[:space:]]*\\b((end)?(function|macro)|return)"
|
||||
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- constant.string:
|
||||
start: "'"
|
||||
end: "'"
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- preproc:
|
||||
start: "\\$(\\{|ENV\\{)"
|
||||
end: "\\}"
|
||||
rules: []
|
||||
|
||||
- identifier.macro: "\\b(APPLE|UNIX|WIN32|CYGWIN|BORLAND|MINGW|MSVC(_IDE|60|71|80|90)?)\\b"
|
||||
|
||||
- comment:
|
||||
start: "#"
|
||||
end: "$"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user