mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-30 22:57:15 +09:00
Compare commits
152 Commits
v1.0rc2
...
terminal-e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d03a5fc998 | ||
|
|
ef4a385380 | ||
|
|
a1fcbde863 | ||
|
|
c0282c4a3c | ||
|
|
0a6e1de404 | ||
|
|
131524e670 | ||
|
|
539495d2f7 | ||
|
|
966dac97f8 | ||
|
|
bf6e596808 | ||
|
|
efa24f5a8d | ||
|
|
432146b068 | ||
|
|
02b6eaaff0 | ||
|
|
dc532e337b | ||
|
|
a952e249b4 | ||
|
|
94465ef1ae | ||
|
|
0a534767f0 | ||
|
|
7937f7038b | ||
|
|
d6a01ad29f | ||
|
|
b1cb583e8c | ||
|
|
ea4d822923 | ||
|
|
583177feff | ||
|
|
3bec1b8c1b | ||
|
|
b992669f5b | ||
|
|
086aa61e5a | ||
|
|
c310053777 | ||
|
|
2041e12eba | ||
|
|
5d00522d4e | ||
|
|
c71e816e37 | ||
|
|
6721ec8e7d | ||
|
|
93eadfb9dc | ||
|
|
cf3ce29a08 | ||
|
|
cd1117c08c | ||
|
|
f247823936 | ||
|
|
a8feef3c12 | ||
|
|
de9707f088 | ||
|
|
9ff396c69f | ||
|
|
4b350d02e0 | ||
|
|
ae3696e82d | ||
|
|
b3f6731db5 | ||
|
|
2b9ef4d406 | ||
|
|
54a34001e3 | ||
|
|
aad7cc7572 | ||
|
|
def5e29b91 | ||
|
|
187ea0da1c | ||
|
|
5b7fa01825 | ||
|
|
c38044106c | ||
|
|
399e3a5ee1 | ||
|
|
fce5b81c22 | ||
|
|
a4ac9f2b7b | ||
|
|
abedeebc0a | ||
|
|
b905400892 | ||
|
|
c4d6f5e584 | ||
|
|
b5232dd24d | ||
|
|
89886f10c7 | ||
|
|
c679500d06 | ||
|
|
76f80bf694 | ||
|
|
a7b72f0e0e | ||
|
|
00eb6725e6 | ||
|
|
af22e0a567 | ||
|
|
98b6f63b70 | ||
|
|
403a99d2ea | ||
|
|
b2735d7b5b | ||
|
|
699ad316e5 | ||
|
|
8617ae5c1f | ||
|
|
c5ac5be764 | ||
|
|
881f57b047 | ||
|
|
1c2b815d95 | ||
|
|
b45fcf5bd7 | ||
|
|
45ec01d197 | ||
|
|
0df7e59ca4 | ||
|
|
89c34ed8b3 | ||
|
|
d9b8a04841 | ||
|
|
ccfe08bc60 | ||
|
|
2e3ee22aca | ||
|
|
226cf399ba | ||
|
|
0f6260601f | ||
|
|
d2254df062 | ||
|
|
3e83d29fb4 | ||
|
|
a432bc7e7b | ||
|
|
486279e1d1 | ||
|
|
3967981b38 | ||
|
|
597c549b5b | ||
|
|
fc2d9bb461 | ||
|
|
832cc366af | ||
|
|
5458605618 | ||
|
|
104af2ef7a | ||
|
|
64ff933451 | ||
|
|
031ed64305 | ||
|
|
1be332a0f9 | ||
|
|
b9d4dbd5e0 | ||
|
|
2e264b342a | ||
|
|
4972db4bf6 | ||
|
|
b70db77c29 | ||
|
|
f8612d1572 | ||
|
|
f9d0c563e4 | ||
|
|
3105205ab8 | ||
|
|
ec29d592da | ||
|
|
62ac9f79f2 | ||
|
|
a6d695f471 | ||
|
|
59d2fa81dd | ||
|
|
4003586456 | ||
|
|
be44dc3ff5 | ||
|
|
c59b1ea387 | ||
|
|
00089a7c01 | ||
|
|
c661c65c8c | ||
|
|
13da5ced15 | ||
|
|
b970b393f2 | ||
|
|
30323116a5 | ||
|
|
2fc274da7d | ||
|
|
b19b36d113 | ||
|
|
b6f5db3692 | ||
|
|
8bdaacaa5e | ||
|
|
c9ead25b1e | ||
|
|
ddff950fcd | ||
|
|
ed6be89d5c | ||
|
|
6e63472930 | ||
|
|
94397a90bd | ||
|
|
216bfaca7e | ||
|
|
9854fc712f | ||
|
|
99635d9491 | ||
|
|
96209cbeb0 | ||
|
|
db520fe9e7 | ||
|
|
93361fe72d | ||
|
|
4499228cdb | ||
|
|
d79e68bbf9 | ||
|
|
ec9eab8a3e | ||
|
|
628cdd34aa | ||
|
|
20d6dffce9 | ||
|
|
afa58a984a | ||
|
|
209cdccdc5 | ||
|
|
2761f57565 | ||
|
|
791a397d55 | ||
|
|
3e428ff505 | ||
|
|
ddc237872c | ||
|
|
ee5ac6a582 | ||
|
|
5df28c76e8 | ||
|
|
19c7860f14 | ||
|
|
f6c7c488f5 | ||
|
|
bc6c9772cd | ||
|
|
fccec47ae5 | ||
|
|
eda08a994a | ||
|
|
f8071af717 | ||
|
|
6ce8fe3ce1 | ||
|
|
00e385b871 | ||
|
|
da98a2e9ec | ||
|
|
59b7555f01 | ||
|
|
8cef0abf6a | ||
|
|
56224c9184 | ||
|
|
40523871fa | ||
|
|
90e0a2ec1a | ||
|
|
aa9dbdde3e | ||
|
|
da7bc997ff |
9
.github/ISSUE_TEMPLATE
vendored
Normal file
9
.github/ISSUE_TEMPLATE
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
## Description of the problem or steps to reproduce
|
||||
|
||||
## Specifications
|
||||
|
||||
You can use `micro -version` to get the commit hash.
|
||||
|
||||
Commit hash:
|
||||
OS:
|
||||
Terminal:
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
./micro
|
||||
!cmd/micro
|
||||
binaries/
|
||||
tmp.sh
|
||||
test/
|
||||
|
||||
24
Makefile
24
Makefile
@@ -2,19 +2,39 @@
|
||||
|
||||
VERSION = $(shell git describe --tags --abbrev=0)
|
||||
HASH = $(shell git rev-parse --short HEAD)
|
||||
DATE = $(shell go run tools/build-date.go)
|
||||
|
||||
build: tcell
|
||||
go build -ldflags "-X main.Version=$(VERSION) -X main.CommitHash=$(HASH) -X 'main.CompileDate=$(shell date -u '+%B %d, %Y')'" -o micro ./cmd/micro
|
||||
# Builds micro after checking dependencies but without updating the runtime
|
||||
build: deps tcell
|
||||
go build -ldflags "-X main.Version=$(VERSION) -X main.CommitHash=$(HASH) -X 'main.CompileDate=$(DATE)'" ./cmd/micro
|
||||
|
||||
# Builds micro after building the runtime and checking dependencies
|
||||
build-all: runtime build
|
||||
|
||||
# Builds micro without checking for dependencies
|
||||
build-quick:
|
||||
go build -ldflags "-X main.Version=$(VERSION) -X main.CommitHash=$(HASH) -X 'main.CompileDate=$(DATE)'" ./cmd/micro
|
||||
|
||||
# Same as 'build' but installs to $GOPATH/bin afterward
|
||||
install: build
|
||||
mv micro $(GOPATH)/bin
|
||||
|
||||
# Same as 'build-all' but installs to $GOPATH/bin afterward
|
||||
install-all: runtime install
|
||||
|
||||
# Same as 'build-quick' but installs to $GOPATH/bin afterward
|
||||
install-quick: build-quick
|
||||
mv micro $(GOPATH)/bin
|
||||
|
||||
# Updates tcell
|
||||
tcell:
|
||||
git -C $(GOPATH)/src/github.com/zyedidia/tcell pull
|
||||
|
||||
# Checks for dependencies
|
||||
deps:
|
||||
go get -d ./cmd/micro
|
||||
|
||||
# Builds the runtime
|
||||
runtime:
|
||||
go get -u github.com/jteeuwen/go-bindata/...
|
||||
$(GOPATH)/bin/go-bindata -nometadata -o runtime.go runtime/...
|
||||
|
||||
63
README.md
63
README.md
@@ -1,19 +1,22 @@
|
||||
# 
|
||||
|
||||
[](https://travis-ci.org/zyedidia/micro)
|
||||

|
||||
[](https://goreportcard.com/report/github.com/zyedidia/micro)
|
||||
[](https://gitter.im/zyedidia/micro?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://github.com/zyedidia/micro/blob/master/LICENSE)
|
||||
|
||||
> Micro is still a work in progress
|
||||
|
||||
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. It comes as one single, batteries-included, static binary with no dependencies, and you can download and use it right now.
|
||||
|
||||
As the name indicates, micro aims to be somewhat of a successor to the nano editor by being easy to install and use in a pinch, but micro also aims to be
|
||||
enjoyable to use full time, whether you work in the terminal because you prefer it (like me), or because you need to (over ssh).
|
||||
|
||||
Here is a picture of micro editing its source code.
|
||||
|
||||

|
||||
|
||||
To see more screenshots of micro, showcasing all of the default colorschemes, see [here](http://zbyedidia.webfactional.com/micro/screenshots.html).
|
||||
|
||||
# Features
|
||||
|
||||
* Easy to use and to install
|
||||
@@ -22,11 +25,13 @@ Here is a picture of micro editing its source code.
|
||||
* Keybindings can be rebound to your liking
|
||||
* Sane defaults
|
||||
* You shouldn't have to configure much out of the box (and it is extremely easy to configure)
|
||||
* Splits and tabs
|
||||
* Extremely good mouse support
|
||||
* This means mouse dragging to create a selection, double click to select by word, and triple click to select by line
|
||||
* Cross platform (It should work on all the platforms Go runs on)
|
||||
* Note that while Windows is supported, there are still some bugs that need to be worked out
|
||||
* Plugin system (plugins are written in Lua)
|
||||
* Persistent undo
|
||||
* Automatic linting and error notifications
|
||||
* Syntax highlighting (for over [75 languages](runtime/syntax)!)
|
||||
* Colorscheme support
|
||||
@@ -35,24 +40,22 @@ Here is a picture of micro editing its source code.
|
||||
* Copy and paste with the system clipboard
|
||||
* Small and simple
|
||||
* Easily configurable
|
||||
* Macros
|
||||
* Common editor things such as undo/redo, line numbers, unicode support...
|
||||
|
||||
Although not yet implemented, I hope to add more features such as autocompletion ([#174](https://github.com/zyedidia/micro/issues/174)), and multiple cursors ([#5](https://github.com/zyedidia/micro/issues/5)) in the future.
|
||||
|
||||
# Installation
|
||||
|
||||
To install micro, you can download a prebuilt binary, or you can build it from source.
|
||||
To install micro, you can download a [prebuilt binary](https://github.com/zyedidia/micro/releases), or you can build it from source.
|
||||
|
||||
You can also install micro with a few package managers (on OSX, Arch Linux, and CRUX).
|
||||
See this [wiki page](https://github.com/zyedidia/micro/wiki/Installing-Micro) for details.
|
||||
|
||||
Please note that micro uses the amazing [tcell library](https://github.com/gdamore/tcell), but this
|
||||
means that micro is restricted to the platforms tcell supports. As a result, micro does not support
|
||||
Plan9, NaCl, and Cygwin (although this may change in the future).
|
||||
If you want more information about ways to install micro, see this [wiki page](https://github.com/zyedidia/micro/wiki/Installing-Micro)
|
||||
|
||||
### Prebuilt binaries
|
||||
|
||||
All you need to install micro is one file, the binary itself. It's as simple as that!
|
||||
|
||||
You can download the correct binary for your operating system from the list in the [nightly build release](https://github.com/zyedidia/micro/releases).
|
||||
Download the binary from the [releases](https://github.com/zyedidia/micro/releases) page.
|
||||
|
||||
On that page you'll see the nightly release, which contains binaries for micro which are built every night,
|
||||
and you'll see all the stable releases with the corresponding binaries.
|
||||
@@ -63,13 +66,13 @@ If you'd like to see more information after installing micro, run `micro -versio
|
||||
|
||||
If your operating system does not have binary, but does run Go, you can build from source.
|
||||
|
||||
Make sure that you have Go version 1.5 or greater (Go 1.4 will work for the systems like support CGO then).
|
||||
Make sure that you have Go version 1.5 or greater (Go 1.4 will work if your version supports CGO).
|
||||
|
||||
```sh
|
||||
go get -u github.com/zyedidia/micro/...
|
||||
```
|
||||
|
||||
### Clipboard support
|
||||
### Linux clipboard support
|
||||
|
||||
On Linux, clipboard support requires 'xclip' or 'xsel' command to be installed.
|
||||
|
||||
@@ -81,6 +84,26 @@ sudo apt-get install xclip
|
||||
|
||||
If you don't have xclip or xsel, micro will use an internal clipboard for copy and paste, but it won't work with external applications.
|
||||
|
||||
### Colors and syntax highlighting
|
||||
|
||||
If you open micro and it doesn't seem like syntax highlighting is working, this is probably because
|
||||
you are using a terminal which does not support 256 color. Try changing the colorscheme to `simple`
|
||||
by running `> set colorscheme simple`.
|
||||
|
||||
If you are using the default ubuntu terminal, to enable 256 make sure your `TERM` variable is set
|
||||
to `xterm-256color`.
|
||||
|
||||
Many of the Windows terminals don't support more than 16 colors, which means
|
||||
that micro's default colorscheme won't look very good. You can either set
|
||||
the colorscheme to `simple`, or download a better terminal emulator, like
|
||||
mintty.
|
||||
|
||||
### Plan9, NaCl, Cygwin
|
||||
|
||||
Please note that micro uses the amazing [tcell library](https://github.com/gdamore/tcell), but this
|
||||
means that micro is restricted to the platforms tcell supports. As a result, micro does not support
|
||||
Plan9, NaCl, and Cygwin (although this may change in the future).
|
||||
|
||||
# Usage
|
||||
|
||||
Once you have built the editor, simply start it by running `micro path/to/file.txt` or simply `micro` to open an empty buffer.
|
||||
@@ -100,10 +123,22 @@ click to enable line selection.
|
||||
# Documentation and Help
|
||||
|
||||
Micro has a built-in help system which you can access by pressing `CtrlE` and typing `help`. Additionally, you can
|
||||
view the help files online [here](https://github.com/zyedidia/micro/tree/master/runtime/help).
|
||||
view the help files here:
|
||||
|
||||
* [main help](https://github.com/zyedidia/micro/tree/master/runtime/help/help.md)
|
||||
* [keybindings](https://github.com/zyedidia/micro/tree/master/runtime/help/keybindings.md)
|
||||
* [commands](https://github.com/zyedidia/micro/tree/master/runtime/help/commands.md)
|
||||
* [colors](https://github.com/zyedidia/micro/tree/master/runtime/help/colors.md)
|
||||
* [options](https://github.com/zyedidia/micro/tree/master/runtime/help/options.md)
|
||||
* [plugins](https://github.com/zyedidia/micro/tree/master/runtime/help/plugins.md)
|
||||
|
||||
I also recommend reading the [tutorial](https://github.com/zyedidia/micro/tree/master/runtime/help/tutorial.md) for
|
||||
a brief introduction to the more powerful configuration features micro offers.
|
||||
|
||||
# Contributing
|
||||
|
||||
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 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).
|
||||
|
||||
@@ -44,6 +44,15 @@ func PostActionCall(funcName string, view *View) bool {
|
||||
return relocate
|
||||
}
|
||||
|
||||
func (v *View) deselect(index int) bool {
|
||||
if v.Cursor.HasSelection() {
|
||||
v.Cursor.Loc = v.Cursor.CurSelection[index]
|
||||
v.Cursor.ResetSelection()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Center centers the view on the cursor
|
||||
func (v *View) Center(usePlugin bool) bool {
|
||||
if usePlugin && !PreActionCall("Center", v) {
|
||||
@@ -51,10 +60,11 @@ func (v *View) Center(usePlugin bool) bool {
|
||||
}
|
||||
|
||||
v.Topline = v.Cursor.Y - v.height/2
|
||||
if v.Topline+v.height > v.Buf.NumLines {
|
||||
v.Topline = v.Buf.NumLines - v.height
|
||||
}
|
||||
if v.Topline < 0 {
|
||||
v.Topline = 0
|
||||
} else if v.Topline+v.height > v.Buf.NumLines {
|
||||
v.Topline = v.Buf.NumLines - v.height
|
||||
}
|
||||
|
||||
if usePlugin {
|
||||
@@ -69,10 +79,7 @@ func (v *View) CursorUp(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.Cursor.HasSelection() {
|
||||
v.Cursor.Loc = v.Cursor.CurSelection[0]
|
||||
v.Cursor.ResetSelection()
|
||||
}
|
||||
v.deselect(0)
|
||||
v.Cursor.Up()
|
||||
|
||||
if usePlugin {
|
||||
@@ -87,10 +94,7 @@ func (v *View) CursorDown(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.Cursor.HasSelection() {
|
||||
v.Cursor.Loc = v.Cursor.CurSelection[1]
|
||||
v.Cursor.ResetSelection()
|
||||
}
|
||||
v.deselect(1)
|
||||
v.Cursor.Down()
|
||||
|
||||
if usePlugin {
|
||||
@@ -289,6 +293,8 @@ func (v *View) StartOfLine(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
v.deselect(0)
|
||||
|
||||
v.Cursor.Start()
|
||||
|
||||
if usePlugin {
|
||||
@@ -303,6 +309,8 @@ func (v *View) EndOfLine(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
v.deselect(0)
|
||||
|
||||
v.Cursor.End()
|
||||
|
||||
if usePlugin {
|
||||
@@ -353,6 +361,8 @@ func (v *View) CursorStart(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
v.deselect(0)
|
||||
|
||||
v.Cursor.X = 0
|
||||
v.Cursor.Y = 0
|
||||
|
||||
@@ -368,6 +378,8 @@ func (v *View) CursorEnd(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
v.deselect(0)
|
||||
|
||||
v.Cursor.Loc = v.Buf.End()
|
||||
|
||||
if usePlugin {
|
||||
@@ -586,21 +598,21 @@ func (v *View) IndentSelection(usePlugin bool) bool {
|
||||
v.Buf.Insert(Loc{0, i}, Spaces(tabsize))
|
||||
if i == start {
|
||||
if v.Cursor.CurSelection[0].X > 0 {
|
||||
v.Cursor.CurSelection[0] = v.Cursor.CurSelection[0].Move(tabsize, v.Buf)
|
||||
v.Cursor.SetSelectionStart(v.Cursor.CurSelection[0].Move(tabsize, v.Buf))
|
||||
}
|
||||
}
|
||||
if i == end {
|
||||
v.Cursor.CurSelection[1] = Loc{endX + tabsize + 1, end}
|
||||
v.Cursor.SetSelectionEnd(Loc{endX + tabsize + 1, end})
|
||||
}
|
||||
} else {
|
||||
v.Buf.Insert(Loc{0, i}, "\t")
|
||||
if i == start {
|
||||
if v.Cursor.CurSelection[0].X > 0 {
|
||||
v.Cursor.CurSelection[0] = v.Cursor.CurSelection[0].Move(1, v.Buf)
|
||||
v.Cursor.SetSelectionStart(v.Cursor.CurSelection[0].Move(1, v.Buf))
|
||||
}
|
||||
}
|
||||
if i == end {
|
||||
v.Cursor.CurSelection[1] = Loc{endX + 2, end}
|
||||
v.Cursor.SetSelectionEnd(Loc{endX + 2, end})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -635,22 +647,22 @@ func (v *View) OutdentSelection(usePlugin bool) bool {
|
||||
v.Buf.Remove(Loc{0, i}, Loc{1, i})
|
||||
if i == start {
|
||||
if v.Cursor.CurSelection[0].X > 0 {
|
||||
v.Cursor.CurSelection[0] = v.Cursor.CurSelection[0].Move(-1, v.Buf)
|
||||
v.Cursor.SetSelectionStart(v.Cursor.CurSelection[0].Move(-1, v.Buf))
|
||||
}
|
||||
}
|
||||
if i == end {
|
||||
v.Cursor.CurSelection[1] = Loc{endX - j, end}
|
||||
v.Cursor.SetSelectionEnd(Loc{endX - j, end})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
v.Buf.Remove(Loc{0, i}, Loc{1, i})
|
||||
if i == start {
|
||||
if v.Cursor.CurSelection[0].X > 0 {
|
||||
v.Cursor.CurSelection[0] = v.Cursor.CurSelection[0].Move(-1, v.Buf)
|
||||
v.Cursor.SetSelectionStart(v.Cursor.CurSelection[0].Move(-1, v.Buf))
|
||||
}
|
||||
}
|
||||
if i == end {
|
||||
v.Cursor.CurSelection[1] = Loc{endX, end}
|
||||
v.Cursor.SetSelectionEnd(Loc{endX, end})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -677,6 +689,9 @@ func (v *View) InsertTab(usePlugin bool) bool {
|
||||
// Insert a tab
|
||||
if v.Buf.Settings["tabstospaces"].(bool) {
|
||||
tabSize := int(v.Buf.Settings["tabsize"].(float64))
|
||||
if remainder := v.Cursor.Loc.X % tabSize; remainder != 0 {
|
||||
tabSize = tabSize - remainder
|
||||
}
|
||||
v.Buf.Insert(v.Cursor.Loc, Spaces(tabSize))
|
||||
for i := 0; i < tabSize; i++ {
|
||||
v.Cursor.Right()
|
||||
@@ -706,6 +721,8 @@ func (v *View) Save(usePlugin bool) bool {
|
||||
if v.Buf.Path == "" {
|
||||
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
|
||||
} else {
|
||||
@@ -835,7 +852,7 @@ func (v *View) Copy(usePlugin bool) bool {
|
||||
}
|
||||
|
||||
if v.Cursor.HasSelection() {
|
||||
clipboard.WriteAll(v.Cursor.GetSelection())
|
||||
clipboard.WriteAll(v.Cursor.GetSelection(), "clipboard")
|
||||
v.freshClip = true
|
||||
messenger.Message("Copied selection")
|
||||
}
|
||||
@@ -858,10 +875,10 @@ func (v *View) CutLine(usePlugin bool) bool {
|
||||
}
|
||||
if v.freshClip == true {
|
||||
if v.Cursor.HasSelection() {
|
||||
if clip, err := clipboard.ReadAll(); err != nil {
|
||||
if clip, err := clipboard.ReadAll("clipboard"); err != nil {
|
||||
messenger.Error(err)
|
||||
} else {
|
||||
clipboard.WriteAll(clip + v.Cursor.GetSelection())
|
||||
clipboard.WriteAll(clip+v.Cursor.GetSelection(), "clipboard")
|
||||
}
|
||||
}
|
||||
} else if time.Since(v.lastCutTime)/time.Second > 10*time.Second || v.freshClip == false {
|
||||
@@ -886,7 +903,7 @@ func (v *View) Cut(usePlugin bool) bool {
|
||||
}
|
||||
|
||||
if v.Cursor.HasSelection() {
|
||||
clipboard.WriteAll(v.Cursor.GetSelection())
|
||||
clipboard.WriteAll(v.Cursor.GetSelection(), "clipboard")
|
||||
v.Cursor.DeleteSelection()
|
||||
v.Cursor.ResetSelection()
|
||||
v.freshClip = true
|
||||
@@ -945,18 +962,23 @@ func (v *View) Paste(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
leadingWS := GetLeadingWhitespace(v.Buf.Line(v.Cursor.Y))
|
||||
clip, _ := clipboard.ReadAll("clipboard")
|
||||
v.paste(clip)
|
||||
|
||||
if v.Cursor.HasSelection() {
|
||||
v.Cursor.DeleteSelection()
|
||||
v.Cursor.ResetSelection()
|
||||
if usePlugin {
|
||||
return PostActionCall("Paste", v)
|
||||
}
|
||||
clip, _ := clipboard.ReadAll()
|
||||
clip = strings.Replace(clip, "\n", "\n"+leadingWS, -1)
|
||||
v.Buf.Insert(v.Cursor.Loc, clip)
|
||||
v.Cursor.Loc = v.Cursor.Loc.Move(Count(clip), v.Buf)
|
||||
v.freshClip = false
|
||||
messenger.Message("Pasted clipboard")
|
||||
return true
|
||||
}
|
||||
|
||||
// PastePrimary pastes from the primary clipboard (only use on linux)
|
||||
func (v *View) PastePrimary(usePlugin bool) bool {
|
||||
if usePlugin && !PreActionCall("Paste", v) {
|
||||
return false
|
||||
}
|
||||
|
||||
clip, _ := clipboard.ReadAll("primary")
|
||||
v.paste(clip)
|
||||
|
||||
if usePlugin {
|
||||
return PostActionCall("Paste", v)
|
||||
@@ -970,8 +992,8 @@ func (v *View) SelectAll(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
v.Cursor.CurSelection[0] = v.Buf.Start()
|
||||
v.Cursor.CurSelection[1] = v.Buf.End()
|
||||
v.Cursor.SetSelectionStart(v.Buf.Start())
|
||||
v.Cursor.SetSelectionEnd(v.Buf.End())
|
||||
// Put the cursor at the beginning
|
||||
v.Cursor.X = 0
|
||||
v.Cursor.Y = 0
|
||||
@@ -988,11 +1010,14 @@ func (v *View) OpenFile(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.CanClose("Continue? (yes, no, save) ") {
|
||||
if v.CanClose() {
|
||||
filename, canceled := messenger.Prompt("File to open: ", "Open", FileCompletion)
|
||||
if canceled {
|
||||
return false
|
||||
}
|
||||
// the filename might or might not be quoted, so unquote first then join the strings.
|
||||
filename = strings.Join(SplitCommandArgs(filename), " ")
|
||||
|
||||
home, _ := homedir.Dir()
|
||||
filename = strings.Replace(filename, "~", home, 1)
|
||||
file, err := ioutil.ReadFile(filename)
|
||||
@@ -1088,6 +1113,8 @@ func (v *View) CursorPageUp(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
v.deselect(0)
|
||||
|
||||
if v.Cursor.HasSelection() {
|
||||
v.Cursor.Loc = v.Cursor.CurSelection[0]
|
||||
v.Cursor.ResetSelection()
|
||||
@@ -1106,6 +1133,8 @@ func (v *View) CursorPageDown(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
v.deselect(0)
|
||||
|
||||
if v.Cursor.HasSelection() {
|
||||
v.Cursor.Loc = v.Cursor.CurSelection[1]
|
||||
v.Cursor.ResetSelection()
|
||||
@@ -1284,7 +1313,7 @@ func (v *View) Quit(usePlugin bool) bool {
|
||||
}
|
||||
|
||||
// Make sure not to quit if there are unsaved changes
|
||||
if v.CanClose("Quit anyway? (yes, no, save) ") {
|
||||
if v.CanClose() {
|
||||
v.CloseBuffer()
|
||||
if len(tabs[curTab].views) > 1 {
|
||||
v.splitNode.Delete()
|
||||
@@ -1321,6 +1350,39 @@ func (v *View) Quit(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// QuitAll quits the whole editor; all splits and tabs
|
||||
func (v *View) QuitAll(usePlugin bool) bool {
|
||||
if usePlugin && !PreActionCall("QuitAll", v) {
|
||||
return false
|
||||
}
|
||||
|
||||
closeAll := true
|
||||
for _, tab := range tabs {
|
||||
for _, v := range tab.views {
|
||||
if !v.CanClose() {
|
||||
closeAll = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if closeAll {
|
||||
for _, tab := range tabs {
|
||||
for _, v := range tab.views {
|
||||
v.CloseBuffer()
|
||||
}
|
||||
}
|
||||
|
||||
if usePlugin {
|
||||
PostActionCall("QuitAll", v)
|
||||
}
|
||||
|
||||
screen.Fini()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// AddTab adds a new tab with an empty buffer
|
||||
func (v *View) AddTab(usePlugin bool) bool {
|
||||
if usePlugin && !PreActionCall("AddTab", v) {
|
||||
@@ -1419,6 +1481,62 @@ func (v *View) PreviousSplit(usePlugin bool) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
var curMacro []interface{}
|
||||
var recordingMacro bool
|
||||
|
||||
func (v *View) ToggleMacro(usePlugin bool) bool {
|
||||
if usePlugin && !PreActionCall("ToggleMacro", v) {
|
||||
return false
|
||||
}
|
||||
|
||||
recordingMacro = !recordingMacro
|
||||
|
||||
if recordingMacro {
|
||||
curMacro = []interface{}{}
|
||||
messenger.Message("Recording")
|
||||
} else {
|
||||
messenger.Message("Stopped recording")
|
||||
}
|
||||
|
||||
if usePlugin {
|
||||
return PostActionCall("ToggleMacro", v)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (v *View) PlayMacro(usePlugin bool) bool {
|
||||
if usePlugin && !PreActionCall("PlayMacro", v) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, action := range curMacro {
|
||||
switch t := action.(type) {
|
||||
case rune:
|
||||
// Insert a character
|
||||
if v.Cursor.HasSelection() {
|
||||
v.Cursor.DeleteSelection()
|
||||
v.Cursor.ResetSelection()
|
||||
}
|
||||
v.Buf.Insert(v.Cursor.Loc, string(t))
|
||||
v.Cursor.Right()
|
||||
|
||||
for _, pl := range loadedPlugins {
|
||||
_, err := Call(pl+".onRune", string(t), v)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "function does not exist") {
|
||||
TermMessage(err)
|
||||
}
|
||||
}
|
||||
case func(*View, bool) bool:
|
||||
t(v, true)
|
||||
}
|
||||
}
|
||||
|
||||
if usePlugin {
|
||||
return PostActionCall("PlayMacro", v)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// None is no action
|
||||
func None() bool {
|
||||
return false
|
||||
|
||||
@@ -8,19 +8,22 @@ import (
|
||||
"github.com/mitchellh/go-homedir"
|
||||
)
|
||||
|
||||
var pluginCompletions []func(string) []string
|
||||
|
||||
// This file is meant (for now) for autocompletion in command mode, not
|
||||
// while coding. This helps micro autocomplete commands and then filenames
|
||||
// for example with `vsplit filename`.
|
||||
|
||||
// FileComplete autocompletes filenames
|
||||
func FileComplete(input string) (string, []string) {
|
||||
dirs := strings.Split(input, "/")
|
||||
var sep string = string(os.PathSeparator)
|
||||
dirs := strings.Split(input, sep)
|
||||
var files []os.FileInfo
|
||||
var err error
|
||||
if len(dirs) > 1 {
|
||||
home, _ := homedir.Dir()
|
||||
|
||||
directories := strings.Join(dirs[:len(dirs)-1], "/")
|
||||
directories := strings.Join(dirs[:len(dirs)-1], sep)
|
||||
if strings.HasPrefix(directories, "~") {
|
||||
directories = strings.Replace(directories, "~", home, 1)
|
||||
}
|
||||
@@ -35,7 +38,7 @@ func FileComplete(input string) (string, []string) {
|
||||
for _, f := range files {
|
||||
name := f.Name()
|
||||
if f.IsDir() {
|
||||
name += "/"
|
||||
name += sep
|
||||
}
|
||||
if strings.HasPrefix(name, dirs[len(dirs)-1]) {
|
||||
suggestions = append(suggestions, name)
|
||||
@@ -45,10 +48,14 @@ func FileComplete(input string) (string, []string) {
|
||||
var chosen string
|
||||
if len(suggestions) == 1 {
|
||||
if len(dirs) > 1 {
|
||||
chosen = strings.Join(dirs[:len(dirs)-1], "/") + "/" + suggestions[0]
|
||||
chosen = strings.Join(dirs[:len(dirs)-1], sep) + sep + suggestions[0]
|
||||
} else {
|
||||
chosen = suggestions[0]
|
||||
}
|
||||
} else {
|
||||
if len(dirs) > 1 {
|
||||
chosen = strings.Join(dirs[:len(dirs)-1], sep) + sep
|
||||
}
|
||||
}
|
||||
|
||||
return chosen, suggestions
|
||||
@@ -88,6 +95,15 @@ func HelpComplete(input string) (string, []string) {
|
||||
return chosen, suggestions
|
||||
}
|
||||
|
||||
func contains(s []string, e string) bool {
|
||||
for _, a := range s {
|
||||
if a == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// OptionComplete autocompletes options
|
||||
func OptionComplete(input string) (string, []string) {
|
||||
var suggestions []string
|
||||
@@ -98,7 +114,7 @@ func OptionComplete(input string) (string, []string) {
|
||||
}
|
||||
}
|
||||
for option := range localSettings {
|
||||
if strings.HasPrefix(option, input) {
|
||||
if strings.HasPrefix(option, input) && !contains(suggestions, option) {
|
||||
suggestions = append(suggestions, option)
|
||||
}
|
||||
}
|
||||
@@ -109,3 +125,24 @@ func OptionComplete(input string) (string, []string) {
|
||||
}
|
||||
return chosen, suggestions
|
||||
}
|
||||
|
||||
// MakeCompletion registeres a function from a plugin for autocomplete commands
|
||||
func MakeCompletion(function string) Completion {
|
||||
pluginCompletions = append(pluginCompletions, LuaFunctionComplete(function))
|
||||
return Completion(-len(pluginCompletions))
|
||||
}
|
||||
|
||||
// PluginComplete autocompletes from plugin function
|
||||
func PluginComplete(complete Completion, input string) (chosen string, suggestions []string) {
|
||||
idx := int(-complete) - 1
|
||||
|
||||
if len(pluginCompletions) <= idx {
|
||||
return "", nil
|
||||
}
|
||||
suggestions = pluginCompletions[idx](input)
|
||||
|
||||
if len(suggestions) == 1 {
|
||||
chosen = suggestions[0]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/yosuke-furukawa/json5/encoding/json5"
|
||||
"github.com/zyedidia/tcell"
|
||||
)
|
||||
|
||||
@@ -55,6 +55,7 @@ var bindingActions = map[string]func(*View, bool) bool{
|
||||
"IndentSelection": (*View).IndentSelection,
|
||||
"OutdentSelection": (*View).OutdentSelection,
|
||||
"Paste": (*View).Paste,
|
||||
"PastePrimary": (*View).PastePrimary,
|
||||
"SelectAll": (*View).SelectAll,
|
||||
"OpenFile": (*View).OpenFile,
|
||||
"Start": (*View).Start,
|
||||
@@ -72,11 +73,14 @@ var bindingActions = map[string]func(*View, bool) bool{
|
||||
"ShellMode": (*View).ShellMode,
|
||||
"CommandMode": (*View).CommandMode,
|
||||
"Quit": (*View).Quit,
|
||||
"QuitAll": (*View).QuitAll,
|
||||
"AddTab": (*View).AddTab,
|
||||
"PreviousTab": (*View).PreviousTab,
|
||||
"NextTab": (*View).NextTab,
|
||||
"NextSplit": (*View).NextSplit,
|
||||
"PreviousSplit": (*View).PreviousSplit,
|
||||
"ToggleMacro": (*View).ToggleMacro,
|
||||
"PlayMacro": (*View).PlayMacro,
|
||||
|
||||
// This was changed to InsertNewline but I don't want to break backwards compatibility
|
||||
"InsertEnter": (*View).InsertNewline,
|
||||
@@ -235,7 +239,7 @@ func InitBindings() {
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(input, &parsed)
|
||||
err = json5.Unmarshal(input, &parsed)
|
||||
if err != nil {
|
||||
TermMessage("Error reading bindings.json:", err.Error())
|
||||
}
|
||||
@@ -393,6 +397,8 @@ func DefaultBindings() map[string]string {
|
||||
"CtrlBackslash": "NextTab",
|
||||
"Home": "StartOfLine",
|
||||
"End": "EndOfLine",
|
||||
"CtrlHome": "CursorStart",
|
||||
"CtrlEnd": "CursorEnd",
|
||||
"PageUp": "CursorPageUp",
|
||||
"PageDown": "CursorPageDown",
|
||||
"CtrlG": "ToggleHelp",
|
||||
@@ -404,6 +410,8 @@ func DefaultBindings() map[string]string {
|
||||
"CtrlQ": "Quit",
|
||||
"CtrlE": "CommandMode",
|
||||
"CtrlW": "NextSplit",
|
||||
"CtrlU": "ToggleMacro",
|
||||
"CtrlJ": "PlayMacro",
|
||||
|
||||
// Emacs-style keybindings
|
||||
"Alt-f": "WordRight",
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
@@ -85,10 +87,36 @@ func NewBuffer(txt []byte, path string) *Buffer {
|
||||
}
|
||||
|
||||
// Put the cursor at the first spot
|
||||
cursorStartX := 0
|
||||
cursorStartY := 0
|
||||
// If -startpos LINE,COL was passed, use start position LINE,COL
|
||||
if len(*flagStartPos) > 0 {
|
||||
positions := strings.Split(*flagStartPos, ",")
|
||||
if len(positions) == 2 {
|
||||
lineNum, errPos1 := strconv.Atoi(positions[0])
|
||||
colNum, errPos2 := strconv.Atoi(positions[1])
|
||||
if errPos1 == nil && errPos2 == nil {
|
||||
cursorStartX = colNum
|
||||
cursorStartY = lineNum - 1
|
||||
// Check to avoid line overflow
|
||||
if cursorStartY > b.NumLines {
|
||||
cursorStartY = b.NumLines - 1
|
||||
} else if cursorStartY < 0 {
|
||||
cursorStartY = 0
|
||||
}
|
||||
// Check to avoid column overflow
|
||||
if cursorStartX > len(b.Line(cursorStartY)) {
|
||||
cursorStartX = len(b.Line(cursorStartY))
|
||||
} else if cursorStartX < 0 {
|
||||
cursorStartX = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
b.Cursor = Cursor{
|
||||
Loc: Loc{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
X: cursorStartX,
|
||||
Y: cursorStartY,
|
||||
},
|
||||
buf: b,
|
||||
}
|
||||
@@ -219,6 +247,7 @@ 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()
|
||||
b.Name = filename
|
||||
b.Path = filename
|
||||
@@ -235,6 +264,7 @@ 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.Name = filename
|
||||
b.Path = filename
|
||||
|
||||
@@ -2,11 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/zyedidia/tcell"
|
||||
"io/ioutil"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/zyedidia/tcell"
|
||||
)
|
||||
|
||||
// Colorscheme is a map from string to style -- it represents a colorscheme
|
||||
@@ -15,7 +16,25 @@ type Colorscheme map[string]tcell.Style
|
||||
// The current colorscheme
|
||||
var colorscheme Colorscheme
|
||||
|
||||
var preInstalledColors = []string{"default", "solarized", "solarized-tc", "atom-dark-tc", "monokai", "gruvbox", "zenburn"}
|
||||
var preInstalledColors = []string{"default", "simple", "solarized", "solarized-tc", "atom-dark-tc", "monokai", "gruvbox", "zenburn", "bubblegum"}
|
||||
|
||||
// ColorschemeExists checks if a given colorscheme exists
|
||||
func ColorschemeExists(colorschemeName string) bool {
|
||||
files, _ := ioutil.ReadDir(configDir)
|
||||
for _, f := range files {
|
||||
if f.Name() == colorschemeName+".micro" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range preInstalledColors {
|
||||
if name == colorschemeName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// InitColorscheme picks and initializes the colorscheme when micro starts
|
||||
func InitColorscheme() {
|
||||
@@ -30,6 +49,7 @@ func LoadDefaultColorscheme() {
|
||||
// LoadColorscheme loads the given colorscheme from a directory
|
||||
func LoadColorscheme(colorschemeName, dir string) {
|
||||
files, _ := ioutil.ReadDir(dir)
|
||||
found := false
|
||||
for _, f := range files {
|
||||
if f.Name() == colorschemeName+".micro" {
|
||||
text, err := ioutil.ReadFile(dir + "/" + f.Name())
|
||||
@@ -38,6 +58,7 @@ func LoadColorscheme(colorschemeName, dir string) {
|
||||
continue
|
||||
}
|
||||
colorscheme = ParseColorscheme(string(text))
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,8 +70,13 @@ func LoadColorscheme(colorschemeName, dir string) {
|
||||
continue
|
||||
}
|
||||
colorscheme = ParseColorscheme(string(data))
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
TermMessage(colorschemeName, "is not a valid colorscheme")
|
||||
}
|
||||
}
|
||||
|
||||
// ParseColorscheme parses the text definition for a colorscheme and returns the corresponding object
|
||||
|
||||
@@ -27,6 +27,7 @@ var commands map[string]Command
|
||||
var commandActions = map[string]func([]string){
|
||||
"Set": Set,
|
||||
"SetLocal": SetLocal,
|
||||
"Show": Show,
|
||||
"Run": Run,
|
||||
"Bind": Bind,
|
||||
"Quit": Quit,
|
||||
@@ -68,17 +69,18 @@ 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": StrCommand{"Set", []Completion{OptionCompletion, NoCompletion}},
|
||||
"setlocal": StrCommand{"SetLocal", []Completion{OptionCompletion, NoCompletion}},
|
||||
"bind": StrCommand{"Bind", []Completion{NoCompletion}},
|
||||
"run": StrCommand{"Run", []Completion{NoCompletion}},
|
||||
"quit": StrCommand{"Quit", []Completion{NoCompletion}},
|
||||
"save": StrCommand{"Save", []Completion{NoCompletion}},
|
||||
"replace": StrCommand{"Replace", []Completion{NoCompletion}},
|
||||
"vsplit": StrCommand{"VSplit", []Completion{FileCompletion, NoCompletion}},
|
||||
"hsplit": StrCommand{"HSplit", []Completion{FileCompletion, NoCompletion}},
|
||||
"tab": StrCommand{"Tab", []Completion{FileCompletion, NoCompletion}},
|
||||
"help": StrCommand{"Help", []Completion{HelpCompletion, NoCompletion}},
|
||||
"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}},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,6 +170,7 @@ func NewTab(args []string) {
|
||||
// Set sets an option
|
||||
func Set(args []string) {
|
||||
if len(args) < 2 {
|
||||
messenger.Error("Not enough arguments")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -177,8 +180,10 @@ func Set(args []string) {
|
||||
SetOptionAndSettings(option, value)
|
||||
}
|
||||
|
||||
// SetLocal sets an option local to the buffer
|
||||
func SetLocal(args []string) {
|
||||
if len(args) < 2 {
|
||||
messenger.Error("Not enough arguments")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -191,10 +196,27 @@ func SetLocal(args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Show shows the value of the given option
|
||||
func Show(args []string) {
|
||||
if len(args) < 1 {
|
||||
messenger.Error("Please provide an option to show")
|
||||
return
|
||||
}
|
||||
|
||||
option := GetOption(args[0])
|
||||
|
||||
if option == nil {
|
||||
messenger.Error(args[0], " is not a valid option")
|
||||
return
|
||||
}
|
||||
|
||||
messenger.Message(option)
|
||||
}
|
||||
|
||||
// Bind creates a new keybinding
|
||||
func Bind(args []string) {
|
||||
if len(args) != 2 {
|
||||
messenger.Error("Incorrect number of arguments")
|
||||
if len(args) < 2 {
|
||||
messenger.Error("Not enough arguments")
|
||||
return
|
||||
}
|
||||
BindKey(args[0], args[1])
|
||||
@@ -203,7 +225,7 @@ func Bind(args []string) {
|
||||
// Run runs a shell command in the background
|
||||
func Run(args []string) {
|
||||
// Run a shell command in the background (openTerm is false)
|
||||
HandleShellCommand(strings.Join(args, " "), false)
|
||||
HandleShellCommand(JoinCommandArgs(args...), false)
|
||||
}
|
||||
|
||||
// Quit closes the main view
|
||||
@@ -220,40 +242,20 @@ func Save(args []string) {
|
||||
|
||||
// Replace runs search and replace
|
||||
func Replace(args []string) {
|
||||
// This is a regex to parse the replace expression
|
||||
// We allow no quotes if there are no spaces, but if you want to search
|
||||
// for or replace an expression with spaces, you can add double quotes
|
||||
r := regexp.MustCompile(`"[^"\\]*(?:\\.[^"\\]*)*"|[^\s]*`)
|
||||
replaceCmd := r.FindAllString(strings.Join(args, " "), -1)
|
||||
if len(replaceCmd) < 2 {
|
||||
if len(args) < 2 {
|
||||
// We need to find both a search and replace expression
|
||||
messenger.Error("Invalid replace statement: " + strings.Join(args, " "))
|
||||
return
|
||||
}
|
||||
|
||||
var flags string
|
||||
if len(replaceCmd) == 3 {
|
||||
if len(args) == 3 {
|
||||
// The user included some flags
|
||||
flags = replaceCmd[2]
|
||||
flags = args[2]
|
||||
}
|
||||
|
||||
search := string(replaceCmd[0])
|
||||
replace := string(replaceCmd[1])
|
||||
|
||||
// If the search and replace expressions have quotes, we need to remove those
|
||||
if strings.HasPrefix(search, `"`) && strings.HasSuffix(search, `"`) {
|
||||
search = search[1 : len(search)-1]
|
||||
}
|
||||
if strings.HasPrefix(replace, `"`) && strings.HasSuffix(replace, `"`) {
|
||||
replace = replace[1 : len(replace)-1]
|
||||
}
|
||||
|
||||
// We replace all escaped double quotes to real double quotes
|
||||
search = strings.Replace(search, `\"`, `"`, -1)
|
||||
replace = strings.Replace(replace, `\"`, `"`, -1)
|
||||
// Replace some things so users can actually insert newlines and tabs in replacements
|
||||
replace = strings.Replace(replace, "\\n", "\n", -1)
|
||||
replace = strings.Replace(replace, "\\t", "\t", -1)
|
||||
search := string(args[0])
|
||||
replace := string(args[1])
|
||||
|
||||
regex, err := regexp.Compile(search)
|
||||
if err != nil {
|
||||
@@ -265,15 +267,13 @@ func Replace(args []string) {
|
||||
view := CurView()
|
||||
|
||||
found := 0
|
||||
for {
|
||||
match := regex.FindStringIndex(view.Buf.String())
|
||||
if match == nil {
|
||||
break
|
||||
}
|
||||
found++
|
||||
if strings.Contains(flags, "c") {
|
||||
if strings.Contains(flags, "c") {
|
||||
for {
|
||||
// The 'check' flag was used
|
||||
Search(search, view, true)
|
||||
if !view.Cursor.HasSelection() {
|
||||
break
|
||||
}
|
||||
view.Relocate()
|
||||
if view.Buf.Settings["syntax"].(bool) {
|
||||
view.matches = Match(view)
|
||||
@@ -286,13 +286,14 @@ func Replace(args []string) {
|
||||
view.Cursor.ResetSelection()
|
||||
}
|
||||
messenger.Reset()
|
||||
return
|
||||
break
|
||||
}
|
||||
if choice {
|
||||
view.Cursor.DeleteSelection()
|
||||
view.Buf.Insert(FromCharPos(match[0], view.Buf), replace)
|
||||
view.Buf.Insert(view.Cursor.Loc, replace)
|
||||
view.Cursor.ResetSelection()
|
||||
messenger.Reset()
|
||||
found++
|
||||
} else {
|
||||
if view.Cursor.HasSelection() {
|
||||
searchStart = ToCharPos(view.Cursor.CurSelection[1], view.Buf)
|
||||
@@ -301,16 +302,23 @@ func Replace(args []string) {
|
||||
}
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
}
|
||||
} else {
|
||||
for {
|
||||
match := regex.FindStringIndex(view.Buf.String())
|
||||
if match == nil {
|
||||
break
|
||||
}
|
||||
found++
|
||||
view.Buf.Replace(FromCharPos(match[0], view.Buf), FromCharPos(match[1], view.Buf), replace)
|
||||
}
|
||||
}
|
||||
view.Cursor.Relocate()
|
||||
|
||||
if found > 1 {
|
||||
messenger.Message("Replaced ", found, " occurences of ", search)
|
||||
messenger.Message("Replaced ", found, " occurrences of ", search)
|
||||
} else if found == 1 {
|
||||
messenger.Message("Replaced ", found, " occurence of ", search)
|
||||
messenger.Message("Replaced ", found, " occurrence of ", search)
|
||||
} else {
|
||||
messenger.Message("Nothing matched ", search)
|
||||
}
|
||||
@@ -318,8 +326,8 @@ func Replace(args []string) {
|
||||
|
||||
// RunShellCommand executes a shell command and returns the output/error
|
||||
func RunShellCommand(input string) (string, error) {
|
||||
inputCmd := strings.Split(input, " ")[0]
|
||||
args := strings.Split(input, " ")[1:]
|
||||
inputCmd := SplitCommandArgs(input)[0]
|
||||
args := SplitCommandArgs(input)[1:]
|
||||
|
||||
cmd := exec.Command(inputCmd, args...)
|
||||
outputBytes := &bytes.Buffer{}
|
||||
@@ -335,7 +343,7 @@ func RunShellCommand(input string) (string, error) {
|
||||
// The openTerm argument specifies whether a terminal should be opened (for viewing output
|
||||
// or interacting with stdin)
|
||||
func HandleShellCommand(input string, openTerm bool) {
|
||||
inputCmd := strings.Split(input, " ")[0]
|
||||
inputCmd := SplitCommandArgs(input)[0]
|
||||
if !openTerm {
|
||||
// Simply run the command in the background and notify the user when it's done
|
||||
messenger.Message("Running...")
|
||||
@@ -360,7 +368,7 @@ func HandleShellCommand(input string, openTerm bool) {
|
||||
screen.Fini()
|
||||
screen = nil
|
||||
|
||||
args := strings.Split(input, " ")[1:]
|
||||
args := SplitCommandArgs(input)[1:]
|
||||
|
||||
// Set up everything for the command
|
||||
cmd := exec.Command(inputCmd, args...)
|
||||
@@ -392,12 +400,12 @@ func HandleShellCommand(input string, openTerm bool) {
|
||||
|
||||
// HandleCommand handles input from the user
|
||||
func HandleCommand(input string) {
|
||||
inputCmd := strings.Split(input, " ")[0]
|
||||
args := strings.Split(input, " ")[1:]
|
||||
args := SplitCommandArgs(input)
|
||||
inputCmd := args[0]
|
||||
|
||||
if _, ok := commands[inputCmd]; !ok {
|
||||
messenger.Error("Unkown command ", inputCmd)
|
||||
messenger.Error("Unknown command ", inputCmd)
|
||||
} else {
|
||||
commands[inputCmd].action(args)
|
||||
commands[inputCmd].action(args[1:])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package main
|
||||
|
||||
import "github.com/zyedidia/clipboard"
|
||||
|
||||
// The Cursor struct stores the location of the cursor in the view
|
||||
// The complicated part about the cursor is storing its location.
|
||||
// The cursor must be displayed at an x, y location, but since the buffer
|
||||
@@ -33,6 +35,24 @@ func (c *Cursor) ResetSelection() {
|
||||
c.CurSelection[1] = c.buf.Start()
|
||||
}
|
||||
|
||||
// SetSelectionStart sets the start of the selection
|
||||
func (c *Cursor) SetSelectionStart(pos Loc) {
|
||||
c.CurSelection[0] = pos
|
||||
// Copy to primary clipboard for linux
|
||||
if c.HasSelection() {
|
||||
clipboard.WriteAll(c.GetSelection(), "primary")
|
||||
}
|
||||
}
|
||||
|
||||
// SetSelectionEnd sets the end of the selection
|
||||
func (c *Cursor) SetSelectionEnd(pos Loc) {
|
||||
c.CurSelection[1] = pos
|
||||
// Copy to primary clipboard for linux
|
||||
if c.HasSelection() {
|
||||
clipboard.WriteAll(c.GetSelection(), "primary")
|
||||
}
|
||||
}
|
||||
|
||||
// HasSelection returns whether or not the user has selected anything
|
||||
func (c *Cursor) HasSelection() bool {
|
||||
return c.CurSelection[0] != c.CurSelection[1]
|
||||
@@ -43,7 +63,7 @@ func (c *Cursor) DeleteSelection() {
|
||||
if c.CurSelection[0].GreaterThan(c.CurSelection[1]) {
|
||||
c.buf.Remove(c.CurSelection[1], c.CurSelection[0])
|
||||
c.Loc = c.CurSelection[1]
|
||||
} else if c.GetSelection() == "" {
|
||||
} else if !c.HasSelection() {
|
||||
return
|
||||
} else {
|
||||
c.buf.Remove(c.CurSelection[0], c.CurSelection[1])
|
||||
@@ -62,12 +82,12 @@ func (c *Cursor) GetSelection() string {
|
||||
// SelectLine selects the current line
|
||||
func (c *Cursor) SelectLine() {
|
||||
c.Start()
|
||||
c.CurSelection[0] = c.Loc
|
||||
c.SetSelectionStart(c.Loc)
|
||||
c.End()
|
||||
if c.buf.NumLines-1 > c.Y {
|
||||
c.CurSelection[1] = c.Loc.Move(1, c.buf)
|
||||
c.SetSelectionEnd(c.Loc.Move(1, c.buf))
|
||||
} else {
|
||||
c.CurSelection[1] = c.Loc
|
||||
c.SetSelectionEnd(c.Loc)
|
||||
}
|
||||
|
||||
c.OrigSelection = c.CurSelection
|
||||
@@ -77,13 +97,13 @@ func (c *Cursor) SelectLine() {
|
||||
func (c *Cursor) AddLineToSelection() {
|
||||
if c.Loc.LessThan(c.OrigSelection[0]) {
|
||||
c.Start()
|
||||
c.CurSelection[0] = c.Loc
|
||||
c.CurSelection[1] = c.OrigSelection[1]
|
||||
c.SetSelectionStart(c.Loc)
|
||||
c.SetSelectionEnd(c.OrigSelection[1])
|
||||
}
|
||||
if c.Loc.GreaterThan(c.OrigSelection[1]) {
|
||||
c.End()
|
||||
c.CurSelection[1] = c.Loc.Move(1, c.buf)
|
||||
c.CurSelection[0] = c.OrigSelection[0]
|
||||
c.SetSelectionEnd(c.Loc.Move(1, c.buf))
|
||||
c.SetSelectionStart(c.OrigSelection[0])
|
||||
}
|
||||
|
||||
if c.Loc.LessThan(c.OrigSelection[1]) && c.Loc.GreaterThan(c.OrigSelection[0]) {
|
||||
@@ -98,8 +118,8 @@ func (c *Cursor) SelectWord() {
|
||||
}
|
||||
|
||||
if !IsWordChar(string(c.RuneUnder(c.X))) {
|
||||
c.CurSelection[0] = c.Loc
|
||||
c.CurSelection[1] = c.Loc.Move(1, c.buf)
|
||||
c.SetSelectionStart(c.Loc)
|
||||
c.SetSelectionEnd(c.Loc.Move(1, c.buf))
|
||||
c.OrigSelection = c.CurSelection
|
||||
return
|
||||
}
|
||||
@@ -110,14 +130,14 @@ func (c *Cursor) SelectWord() {
|
||||
backward--
|
||||
}
|
||||
|
||||
c.CurSelection[0] = Loc{backward, c.Y}
|
||||
c.SetSelectionStart(Loc{backward, c.Y})
|
||||
c.OrigSelection[0] = c.CurSelection[0]
|
||||
|
||||
for forward < Count(c.buf.Line(c.Y))-1 && IsWordChar(string(c.RuneUnder(forward+1))) {
|
||||
forward++
|
||||
}
|
||||
|
||||
c.CurSelection[1] = Loc{forward, c.Y}.Move(1, c.buf)
|
||||
c.SetSelectionEnd(Loc{forward, c.Y}.Move(1, c.buf))
|
||||
c.OrigSelection[1] = c.CurSelection[1]
|
||||
c.Loc = c.CurSelection[1]
|
||||
}
|
||||
@@ -136,8 +156,8 @@ func (c *Cursor) AddWordToSelection() {
|
||||
backward--
|
||||
}
|
||||
|
||||
c.CurSelection[0] = Loc{backward, c.Y}
|
||||
c.CurSelection[1] = c.OrigSelection[1]
|
||||
c.SetSelectionStart(Loc{backward, c.Y})
|
||||
c.SetSelectionEnd(c.OrigSelection[1])
|
||||
}
|
||||
|
||||
if c.Loc.GreaterThan(c.OrigSelection[1]) {
|
||||
@@ -147,8 +167,8 @@ func (c *Cursor) AddWordToSelection() {
|
||||
forward++
|
||||
}
|
||||
|
||||
c.CurSelection[1] = Loc{forward, c.Y}.Move(1, c.buf)
|
||||
c.CurSelection[0] = c.OrigSelection[0]
|
||||
c.SetSelectionEnd(Loc{forward, c.Y}.Move(1, c.buf))
|
||||
c.SetSelectionStart(c.OrigSelection[0])
|
||||
}
|
||||
|
||||
c.Loc = c.CurSelection[1]
|
||||
@@ -157,11 +177,11 @@ func (c *Cursor) AddWordToSelection() {
|
||||
// SelectTo selects from the current cursor location to the given location
|
||||
func (c *Cursor) SelectTo(loc Loc) {
|
||||
if loc.GreaterThan(c.OrigSelection[0]) {
|
||||
c.CurSelection[0] = c.OrigSelection[0]
|
||||
c.CurSelection[1] = loc
|
||||
c.SetSelectionStart(c.OrigSelection[0])
|
||||
c.SetSelectionEnd(loc)
|
||||
} else {
|
||||
c.CurSelection[0] = loc
|
||||
c.CurSelection[1] = c.OrigSelection[0]
|
||||
c.SetSelectionStart(loc)
|
||||
c.SetSelectionEnd(c.OrigSelection[0])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ var helpFiles = []string{
|
||||
"colors",
|
||||
"options",
|
||||
"commands",
|
||||
"tutorial",
|
||||
}
|
||||
|
||||
// LoadHelp loads the help text from inside the binary
|
||||
|
||||
@@ -38,6 +38,7 @@ var preInstalledSynFiles = []string{
|
||||
"asm",
|
||||
"awk",
|
||||
"c",
|
||||
"caddyfile",
|
||||
"cmake",
|
||||
"coffeescript",
|
||||
"colortest",
|
||||
@@ -47,6 +48,7 @@ var preInstalledSynFiles = []string{
|
||||
"css",
|
||||
"cython",
|
||||
"d",
|
||||
"dart",
|
||||
"dot",
|
||||
"erb",
|
||||
"fish",
|
||||
@@ -79,9 +81,11 @@ var preInstalledSynFiles = []string{
|
||||
"man",
|
||||
"markdown",
|
||||
"mpdconf",
|
||||
"micro",
|
||||
"nanorc",
|
||||
"nginx",
|
||||
"ocaml",
|
||||
"pascal",
|
||||
"patch",
|
||||
"peg",
|
||||
"perl",
|
||||
@@ -482,7 +486,6 @@ func Match(v *View) SyntaxMatches {
|
||||
for _, value := range indicies {
|
||||
start := runePos(value[0], line)
|
||||
end := runePos(value[1], line)
|
||||
// messenger.Message(start, " ", end)
|
||||
for i := start; i < end; i++ {
|
||||
matches[lineN][i] = rule.style
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/zyedidia/clipboard"
|
||||
"github.com/zyedidia/tcell"
|
||||
@@ -98,6 +97,7 @@ func (m *Messenger) Error(msg ...interface{}) {
|
||||
|
||||
// YesNoPrompt asks the user a yes or no question (waits for y or n) and returns the result
|
||||
func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
|
||||
m.hasPrompt = true
|
||||
m.Message(prompt)
|
||||
|
||||
_, h := screen.Size()
|
||||
@@ -113,17 +113,55 @@ func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
|
||||
switch e.Key() {
|
||||
case tcell.KeyRune:
|
||||
if e.Rune() == 'y' {
|
||||
m.hasPrompt = false
|
||||
return true, false
|
||||
} else if e.Rune() == 'n' {
|
||||
m.hasPrompt = false
|
||||
return false, false
|
||||
}
|
||||
case tcell.KeyCtrlC, tcell.KeyCtrlQ, tcell.KeyEscape:
|
||||
m.hasPrompt = false
|
||||
return false, true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LetterPrompt gives the user a prompt and waits for a one letter response
|
||||
func (m *Messenger) LetterPrompt(prompt string, responses ...rune) (rune, bool) {
|
||||
m.hasPrompt = true
|
||||
m.Message(prompt)
|
||||
|
||||
_, h := screen.Size()
|
||||
for {
|
||||
m.Clear()
|
||||
m.Display()
|
||||
screen.ShowCursor(Count(m.message), h-1)
|
||||
screen.Show()
|
||||
event := <-events
|
||||
|
||||
switch e := event.(type) {
|
||||
case *tcell.EventKey:
|
||||
switch e.Key() {
|
||||
case tcell.KeyRune:
|
||||
for _, r := range responses {
|
||||
if e.Rune() == r {
|
||||
m.Clear()
|
||||
m.Reset()
|
||||
m.hasPrompt = false
|
||||
return r, false
|
||||
}
|
||||
}
|
||||
case tcell.KeyCtrlC, tcell.KeyCtrlQ, tcell.KeyEscape:
|
||||
m.Clear()
|
||||
m.Reset()
|
||||
m.hasPrompt = false
|
||||
return ' ', true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Completion int
|
||||
|
||||
const (
|
||||
@@ -167,7 +205,7 @@ func (m *Messenger) Prompt(prompt, historyType string, completionTypes ...Comple
|
||||
response, canceled = m.response, false
|
||||
m.history[historyType][len(m.history[historyType])-1] = response
|
||||
case tcell.KeyTab:
|
||||
args := strings.Split(m.response, " ")
|
||||
args := SplitCommandArgs(m.response)
|
||||
currentArgNum := len(args) - 1
|
||||
currentArg := args[currentArgNum]
|
||||
var completionType Completion
|
||||
@@ -193,13 +231,16 @@ func (m *Messenger) Prompt(prompt, historyType string, completionTypes ...Comple
|
||||
chosen, suggestions = HelpComplete(currentArg)
|
||||
} else if completionType == OptionCompletion {
|
||||
chosen, suggestions = OptionComplete(currentArg)
|
||||
} else if completionType < NoCompletion {
|
||||
chosen, suggestions = PluginComplete(completionType, currentArg)
|
||||
}
|
||||
|
||||
if len(suggestions) > 1 {
|
||||
chosen = chosen + CommonSubstring(suggestions...)
|
||||
}
|
||||
|
||||
if chosen != "" {
|
||||
if len(args) > 1 {
|
||||
chosen = " " + chosen
|
||||
}
|
||||
m.response = strings.Join(args[:len(args)-1], " ") + chosen
|
||||
m.response = JoinCommandArgs(append(args[:len(args)-1], chosen)...)
|
||||
m.cursorx = Count(m.response)
|
||||
}
|
||||
}
|
||||
@@ -207,18 +248,19 @@ func (m *Messenger) Prompt(prompt, historyType string, completionTypes ...Comple
|
||||
|
||||
m.HandleEvent(event, m.history[historyType])
|
||||
|
||||
messenger.Clear()
|
||||
m.Clear()
|
||||
for _, v := range tabs[curTab].views {
|
||||
v.Display()
|
||||
}
|
||||
DisplayTabs()
|
||||
messenger.Display()
|
||||
m.Display()
|
||||
if len(suggestions) > 1 {
|
||||
m.DisplaySuggestions(suggestions)
|
||||
}
|
||||
screen.Show()
|
||||
}
|
||||
|
||||
m.Clear()
|
||||
m.Reset()
|
||||
return response, canceled
|
||||
}
|
||||
@@ -254,7 +296,7 @@ func (m *Messenger) HandleEvent(event tcell.Event, history []string) {
|
||||
m.cursorx--
|
||||
}
|
||||
case tcell.KeyCtrlV:
|
||||
clip, _ := clipboard.ReadAll()
|
||||
clip, _ := clipboard.ReadAll("clipboard")
|
||||
m.response = Insert(m.response, m.cursorx, clip)
|
||||
m.cursorx += Count(clip)
|
||||
case tcell.KeyRune:
|
||||
@@ -314,11 +356,14 @@ func (m *Messenger) DisplaySuggestions(suggestions []string) {
|
||||
func (m *Messenger) Display() {
|
||||
_, h := screen.Size()
|
||||
if m.hasMessage {
|
||||
runes := []rune(m.message + m.response)
|
||||
for x := 0; x < len(runes); x++ {
|
||||
screen.SetContent(x, h-1, runes[x], nil, m.style)
|
||||
if m.hasPrompt || globalSettings["infobar"].(bool) {
|
||||
runes := []rune(m.message + m.response)
|
||||
for x := 0; x < len(runes); x++ {
|
||||
screen.SetContent(x, h-1, runes[x], nil, m.style)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if m.hasPrompt {
|
||||
screen.ShowCursor(Count(m.message)+m.cursorx, h-1)
|
||||
screen.Show()
|
||||
|
||||
@@ -42,7 +42,7 @@ var (
|
||||
configDir string
|
||||
|
||||
// Version is the version number or commit hash
|
||||
// This should be set by the linker when compiling
|
||||
// These variables should be set by the linker when compiling
|
||||
Version = "Unknown"
|
||||
CommitHash = "Unknown"
|
||||
CompileDate = "Unknown"
|
||||
@@ -64,11 +64,11 @@ var (
|
||||
)
|
||||
|
||||
// LoadInput determines which files should be loaded into buffers
|
||||
// based on the input stored in os.Args
|
||||
// based on the input stored in flag.Args()
|
||||
func LoadInput() []*Buffer {
|
||||
// There are a number of ways micro should start given its input
|
||||
|
||||
// 1. If it is given a files in os.Args, it should open those
|
||||
// 1. If it is given a files in flag.Args(), it should open those
|
||||
|
||||
// 2. If there is no input file and the input is not a terminal, that means
|
||||
// something is being piped in and the stdin should be opened in an
|
||||
@@ -82,18 +82,20 @@ func LoadInput() []*Buffer {
|
||||
var err error
|
||||
var buffers []*Buffer
|
||||
|
||||
if len(os.Args) > 1 {
|
||||
if len(flag.Args()) > 0 {
|
||||
// Option 1
|
||||
// We go through each file and load it
|
||||
for i := 1; i < len(os.Args); i++ {
|
||||
filename = os.Args[i]
|
||||
for i := 0; i < len(flag.Args()); i++ {
|
||||
filename = flag.Args()[i]
|
||||
|
||||
// Check that the file exists
|
||||
if _, e := os.Stat(filename); e == nil {
|
||||
// If it exists we load it into a buffer
|
||||
input, err = ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
TermMessage(err)
|
||||
continue
|
||||
input = []byte{}
|
||||
filename = ""
|
||||
}
|
||||
}
|
||||
// If the file didn't exist, input will be empty, and we'll open an empty buffer
|
||||
@@ -104,6 +106,10 @@ func LoadInput() []*Buffer {
|
||||
// The input is not a terminal, so something is being piped in
|
||||
// and we should read from stdin
|
||||
input, err = ioutil.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
TermMessage("Error reading from stdin: ", err)
|
||||
input = []byte{}
|
||||
}
|
||||
buffers = append(buffers, NewBuffer(input, filename))
|
||||
} else {
|
||||
// Option 3, just open an empty buffer
|
||||
@@ -157,9 +163,29 @@ func InitScreen() {
|
||||
os.Setenv("TERM", "xterm-truecolor")
|
||||
}
|
||||
|
||||
os.Setenv("TCELLDB", configDir+"/.tcelldb")
|
||||
|
||||
// Initilize tcell
|
||||
var err error
|
||||
screen, err = tcell.NewScreen()
|
||||
|
||||
if err != nil && err.Error() == "terminal entry not found" {
|
||||
var termDB []byte
|
||||
termDB, err = MkInfo()
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Terminal entry not found")
|
||||
fmt.Println("Error when trying to read terminfo: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if _, e := os.Stat(configDir); e == nil {
|
||||
ioutil.WriteFile(configDir+"/.tcelldb", termDB, 0644)
|
||||
}
|
||||
|
||||
screen, err = tcell.NewScreen()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
@@ -190,10 +216,24 @@ func RedrawAll() {
|
||||
}
|
||||
|
||||
// Passing -version as a flag will have micro print out the version number
|
||||
var flagVersion = flag.Bool("version", false, "Show the version number")
|
||||
var flagVersion = flag.Bool("version", false, "Show the version number and information")
|
||||
var flagStartPos = flag.String("startpos", "", "LINE,COL to start the cursor at when opening a buffer.")
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
fmt.Println("Usage: micro [OPTIONS] [FILE]...")
|
||||
fmt.Println("Micro's options can be set via command line arguments for quick adjustments. For real configuration, please use the bindings.json file (see 'help options').\n")
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
optionFlags := make(map[string]*string)
|
||||
|
||||
for k, v := range DefaultGlobalSettings() {
|
||||
optionFlags[k] = flag.String(k, "", fmt.Sprintf("The %s option. Default value: '%v'", k, v))
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if *flagVersion {
|
||||
// If -version was passed
|
||||
fmt.Println("Version:", Version)
|
||||
@@ -215,6 +255,7 @@ func main() {
|
||||
|
||||
// Load the user's settings
|
||||
InitGlobalSettings()
|
||||
|
||||
InitCommands()
|
||||
InitBindings()
|
||||
|
||||
@@ -262,6 +303,12 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range optionFlags {
|
||||
if *v != "" {
|
||||
SetOption(k, *v)
|
||||
}
|
||||
}
|
||||
|
||||
// Load all the plugin stuff
|
||||
// We give plugins access to a bunch of variables here which could be useful to them
|
||||
L.SetGlobal("OS", luar.New(L, runtime.GOOS))
|
||||
@@ -279,6 +326,7 @@ func main() {
|
||||
L.SetGlobal("HandleCommand", luar.New(L, HandleCommand))
|
||||
L.SetGlobal("HandleShellCommand", luar.New(L, HandleShellCommand))
|
||||
L.SetGlobal("GetLeadingWhitespace", luar.New(L, GetLeadingWhitespace))
|
||||
L.SetGlobal("MakeCompletion", luar.New(L, MakeCompletion))
|
||||
|
||||
// Used for asynchronous jobs
|
||||
L.SetGlobal("JobStart", luar.New(L, JobStart))
|
||||
@@ -333,20 +381,22 @@ func main() {
|
||||
// If the user left clicked we check a couple things
|
||||
_, h := screen.Size()
|
||||
x, y := e.Position()
|
||||
if y == h-1 && messenger.message != "" {
|
||||
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)
|
||||
clipboard.WriteAll(messenger.message, "primary")
|
||||
continue
|
||||
}
|
||||
|
||||
// We loop through each view in the current tab and make sure the current view
|
||||
// it 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
669
cmd/micro/mkinfo.go
Normal file
669
cmd/micro/mkinfo.go
Normal file
@@ -0,0 +1,669 @@
|
||||
// Copyright 2016 The TCell Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use file except in compliance with the License.
|
||||
// You may obtain a copy of the license at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This command is used to generate suitable configuration files in either
|
||||
// go syntax or in JSON. It defaults to JSON output on stdout. If no
|
||||
// term values are specified on the command line, then $TERM is used.
|
||||
//
|
||||
// Usage is like this:
|
||||
//
|
||||
// mkinfo [-go file.go] [-json file.json] [-quiet] [-nofatal] [<term>...]
|
||||
//
|
||||
// -go specifiles Go output into the named file. Use - for stdout.
|
||||
// -json specifies JSON output in the named file. Use - for stdout
|
||||
// -nofatal indicates that errors loading definitions should not be fatal
|
||||
//
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/zyedidia/tcell"
|
||||
)
|
||||
|
||||
// #include <curses.h>
|
||||
// #include <term.h>
|
||||
// #cgo LDFLAGS: -lcurses
|
||||
//
|
||||
// void noenv() {
|
||||
// use_env(FALSE);
|
||||
// }
|
||||
//
|
||||
// char *tigetstr_good(char *name) {
|
||||
// char *r;
|
||||
// r = tigetstr(name);
|
||||
// if (r == (char *)-1) {
|
||||
// r = NULL;
|
||||
// }
|
||||
// return (r);
|
||||
// }
|
||||
import "C"
|
||||
|
||||
func tigetnum(s string) int {
|
||||
n := C.tigetnum(C.CString(s))
|
||||
return int(n)
|
||||
}
|
||||
|
||||
func tigetflag(s string) bool {
|
||||
n := C.tigetflag(C.CString(s))
|
||||
return n != 0
|
||||
}
|
||||
|
||||
func tigetstr(s string) string {
|
||||
// NB: If the string is invalid, we'll get back -1, which causes
|
||||
// no end of grief. So make sure your capability strings are correct!
|
||||
cs := C.tigetstr_good(C.CString(s))
|
||||
if cs == nil {
|
||||
return ""
|
||||
}
|
||||
return C.GoString(cs)
|
||||
}
|
||||
|
||||
// This program is used to collect data from the system's terminfo library,
|
||||
// and write it into Go source code. That is, we maintain our terminfo
|
||||
// capabilities encoded in the program. It should never need to be run by
|
||||
// an end user, but developers can use this to add codes for additional
|
||||
// terminal types.
|
||||
//
|
||||
// If a terminal name ending with -truecolor is given, and we cannot find
|
||||
// one, we will try to fabricte one from either the -256color (if present)
|
||||
// or the unadorned base name, adding the XTerm specific 24-bit color
|
||||
// escapes. We believe that all 24-bit capable terminals use the same
|
||||
// escape sequences, and terminfo has yet to evolve to support this.
|
||||
func getinfo(name string) (*tcell.Terminfo, error) {
|
||||
addTrueColor := false
|
||||
rsn := C.int(0)
|
||||
C.noenv()
|
||||
rv, _ := C.setupterm(C.CString(name), 1, &rsn)
|
||||
if rv == C.ERR {
|
||||
if strings.HasSuffix(name, "-truecolor") {
|
||||
base := name[:len(name)-len("-truecolor")]
|
||||
// Probably -256color is closest to what we want
|
||||
rv, _ = C.setupterm(C.CString(base+"-256color"), 1,
|
||||
&rsn)
|
||||
// Otherwise try the base
|
||||
if rv == C.ERR {
|
||||
rv, _ = C.setupterm(C.CString(base), 1, &rsn)
|
||||
}
|
||||
if rv != C.ERR {
|
||||
addTrueColor = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if rv == C.ERR {
|
||||
switch rsn {
|
||||
case 1:
|
||||
return nil, errors.New("hardcopy terminal")
|
||||
case 0:
|
||||
return nil, errors.New("terminal definition not found")
|
||||
case -1:
|
||||
return nil, errors.New("terminfo database missing")
|
||||
default:
|
||||
return nil, errors.New("setupterm failed (other)")
|
||||
}
|
||||
}
|
||||
t := &tcell.Terminfo{}
|
||||
t.Name = name
|
||||
t.Colors = tigetnum("colors")
|
||||
t.Columns = tigetnum("cols")
|
||||
t.Lines = tigetnum("lines")
|
||||
t.Bell = tigetstr("bel")
|
||||
t.Clear = tigetstr("clear")
|
||||
t.EnterCA = tigetstr("smcup")
|
||||
t.ExitCA = tigetstr("rmcup")
|
||||
t.ShowCursor = tigetstr("cnorm")
|
||||
t.HideCursor = tigetstr("civis")
|
||||
t.AttrOff = tigetstr("sgr0")
|
||||
t.Underline = tigetstr("smul")
|
||||
t.Bold = tigetstr("bold")
|
||||
t.Blink = tigetstr("blink")
|
||||
t.Dim = tigetstr("dim")
|
||||
t.Reverse = tigetstr("rev")
|
||||
t.EnterKeypad = tigetstr("smkx")
|
||||
t.ExitKeypad = tigetstr("rmkx")
|
||||
t.SetFg = tigetstr("setaf")
|
||||
t.SetBg = tigetstr("setab")
|
||||
t.SetCursor = tigetstr("cup")
|
||||
t.CursorBack1 = tigetstr("cub1")
|
||||
t.CursorUp1 = tigetstr("cuu1")
|
||||
t.KeyF1 = tigetstr("kf1")
|
||||
t.KeyF2 = tigetstr("kf2")
|
||||
t.KeyF3 = tigetstr("kf3")
|
||||
t.KeyF4 = tigetstr("kf4")
|
||||
t.KeyF5 = tigetstr("kf5")
|
||||
t.KeyF6 = tigetstr("kf6")
|
||||
t.KeyF7 = tigetstr("kf7")
|
||||
t.KeyF8 = tigetstr("kf8")
|
||||
t.KeyF9 = tigetstr("kf9")
|
||||
t.KeyF10 = tigetstr("kf10")
|
||||
t.KeyF11 = tigetstr("kf11")
|
||||
t.KeyF12 = tigetstr("kf12")
|
||||
t.KeyF13 = tigetstr("kf13")
|
||||
t.KeyF14 = tigetstr("kf14")
|
||||
t.KeyF15 = tigetstr("kf15")
|
||||
t.KeyF16 = tigetstr("kf16")
|
||||
t.KeyF17 = tigetstr("kf17")
|
||||
t.KeyF18 = tigetstr("kf18")
|
||||
t.KeyF19 = tigetstr("kf19")
|
||||
t.KeyF20 = tigetstr("kf20")
|
||||
t.KeyF21 = tigetstr("kf21")
|
||||
t.KeyF22 = tigetstr("kf22")
|
||||
t.KeyF23 = tigetstr("kf23")
|
||||
t.KeyF24 = tigetstr("kf24")
|
||||
t.KeyF25 = tigetstr("kf25")
|
||||
t.KeyF26 = tigetstr("kf26")
|
||||
t.KeyF27 = tigetstr("kf27")
|
||||
t.KeyF28 = tigetstr("kf28")
|
||||
t.KeyF29 = tigetstr("kf29")
|
||||
t.KeyF30 = tigetstr("kf30")
|
||||
t.KeyF31 = tigetstr("kf31")
|
||||
t.KeyF32 = tigetstr("kf32")
|
||||
t.KeyF33 = tigetstr("kf33")
|
||||
t.KeyF34 = tigetstr("kf34")
|
||||
t.KeyF35 = tigetstr("kf35")
|
||||
t.KeyF36 = tigetstr("kf36")
|
||||
t.KeyF37 = tigetstr("kf37")
|
||||
t.KeyF38 = tigetstr("kf38")
|
||||
t.KeyF39 = tigetstr("kf39")
|
||||
t.KeyF40 = tigetstr("kf40")
|
||||
t.KeyF41 = tigetstr("kf41")
|
||||
t.KeyF42 = tigetstr("kf42")
|
||||
t.KeyF43 = tigetstr("kf43")
|
||||
t.KeyF44 = tigetstr("kf44")
|
||||
t.KeyF45 = tigetstr("kf45")
|
||||
t.KeyF46 = tigetstr("kf46")
|
||||
t.KeyF47 = tigetstr("kf47")
|
||||
t.KeyF48 = tigetstr("kf48")
|
||||
t.KeyF49 = tigetstr("kf49")
|
||||
t.KeyF50 = tigetstr("kf50")
|
||||
t.KeyF51 = tigetstr("kf51")
|
||||
t.KeyF52 = tigetstr("kf52")
|
||||
t.KeyF53 = tigetstr("kf53")
|
||||
t.KeyF54 = tigetstr("kf54")
|
||||
t.KeyF55 = tigetstr("kf55")
|
||||
t.KeyF56 = tigetstr("kf56")
|
||||
t.KeyF57 = tigetstr("kf57")
|
||||
t.KeyF58 = tigetstr("kf58")
|
||||
t.KeyF59 = tigetstr("kf59")
|
||||
t.KeyF60 = tigetstr("kf60")
|
||||
t.KeyF61 = tigetstr("kf61")
|
||||
t.KeyF62 = tigetstr("kf62")
|
||||
t.KeyF63 = tigetstr("kf63")
|
||||
t.KeyF64 = tigetstr("kf64")
|
||||
t.KeyInsert = tigetstr("kich1")
|
||||
t.KeyDelete = tigetstr("kdch1")
|
||||
t.KeyBackspace = tigetstr("kbs")
|
||||
t.KeyHome = tigetstr("khome")
|
||||
t.KeyEnd = tigetstr("kend")
|
||||
t.KeyUp = tigetstr("kcuu1")
|
||||
t.KeyDown = tigetstr("kcud1")
|
||||
t.KeyRight = tigetstr("kcuf1")
|
||||
t.KeyLeft = tigetstr("kcub1")
|
||||
t.KeyPgDn = tigetstr("knp")
|
||||
t.KeyPgUp = tigetstr("kpp")
|
||||
t.KeyBacktab = tigetstr("kcbt")
|
||||
t.KeyExit = tigetstr("kext")
|
||||
t.KeyCancel = tigetstr("kcan")
|
||||
t.KeyPrint = tigetstr("kprt")
|
||||
t.KeyHelp = tigetstr("khlp")
|
||||
t.KeyClear = tigetstr("kclr")
|
||||
t.AltChars = tigetstr("acsc")
|
||||
t.EnterAcs = tigetstr("smacs")
|
||||
t.ExitAcs = tigetstr("rmacs")
|
||||
t.EnableAcs = tigetstr("enacs")
|
||||
t.Mouse = tigetstr("kmous")
|
||||
t.KeyShfRight = tigetstr("kRIT")
|
||||
t.KeyShfLeft = tigetstr("kLFT")
|
||||
t.KeyShfHome = tigetstr("kHOM")
|
||||
t.KeyShfEnd = tigetstr("kEND")
|
||||
|
||||
// Terminfo lacks descriptions for a bunch of modified keys,
|
||||
// but modern XTerm and emulators often have them. Let's add them,
|
||||
// if the shifted right and left arrows are defined.
|
||||
if t.KeyShfRight == "\x1b[1;2C" && t.KeyShfLeft == "\x1b[1;2D" {
|
||||
t.KeyShfUp = "\x1b[1;2A"
|
||||
t.KeyShfDown = "\x1b[1;2B"
|
||||
t.KeyMetaUp = "\x1b[1;9A"
|
||||
t.KeyMetaDown = "\x1b[1;9B"
|
||||
t.KeyMetaRight = "\x1b[1;9C"
|
||||
t.KeyMetaLeft = "\x1b[1;9D"
|
||||
t.KeyAltUp = "\x1b[1;3A"
|
||||
t.KeyAltDown = "\x1b[1;3B"
|
||||
t.KeyAltRight = "\x1b[1;3C"
|
||||
t.KeyAltLeft = "\x1b[1;3D"
|
||||
t.KeyCtrlUp = "\x1b[1;5A"
|
||||
t.KeyCtrlDown = "\x1b[1;5B"
|
||||
t.KeyCtrlRight = "\x1b[1;5C"
|
||||
t.KeyCtrlLeft = "\x1b[1;5D"
|
||||
t.KeyAltShfUp = "\x1b[1;4A"
|
||||
t.KeyAltShfDown = "\x1b[1;4B"
|
||||
t.KeyAltShfRight = "\x1b[1;4C"
|
||||
t.KeyAltShfLeft = "\x1b[1;4D"
|
||||
|
||||
t.KeyMetaShfUp = "\x1b[1;10A"
|
||||
t.KeyMetaShfDown = "\x1b[1;10B"
|
||||
t.KeyMetaShfRight = "\x1b[1;10C"
|
||||
t.KeyMetaShfLeft = "\x1b[1;10D"
|
||||
|
||||
t.KeyCtrlShfUp = "\x1b[1;6A"
|
||||
t.KeyCtrlShfDown = "\x1b[1;6B"
|
||||
t.KeyCtrlShfRight = "\x1b[1;6C"
|
||||
t.KeyCtrlShfLeft = "\x1b[1;6D"
|
||||
}
|
||||
// And also for Home and End
|
||||
if t.KeyShfHome == "\x1b[1;2H" && t.KeyShfEnd == "\x1b[1;2F" {
|
||||
t.KeyCtrlHome = "\x1b[1;5H"
|
||||
t.KeyCtrlEnd = "\x1b[1;5F"
|
||||
t.KeyAltHome = "\x1b[1;9H"
|
||||
t.KeyAltEnd = "\x1b[1;9F"
|
||||
t.KeyCtrlShfHome = "\x1b[1;6H"
|
||||
t.KeyCtrlShfEnd = "\x1b[1;6F"
|
||||
t.KeyAltShfHome = "\x1b[1;4H"
|
||||
t.KeyAltShfEnd = "\x1b[1;4F"
|
||||
t.KeyMetaShfHome = "\x1b[1;10H"
|
||||
t.KeyMetaShfEnd = "\x1b[1;10F"
|
||||
}
|
||||
|
||||
// And the same thing for rxvt and workalikes (Eterm, aterm, etc.)
|
||||
// It seems that urxvt at least send ESC as ALT prefix for these,
|
||||
// although some places seem to indicate a separate ALT key sesquence.
|
||||
if t.KeyShfRight == "\x1b[c" && t.KeyShfLeft == "\x1b[d" {
|
||||
t.KeyShfUp = "\x1b[a"
|
||||
t.KeyShfDown = "\x1b[b"
|
||||
t.KeyCtrlUp = "\x1b[Oa"
|
||||
t.KeyCtrlDown = "\x1b[Ob"
|
||||
t.KeyCtrlRight = "\x1b[Oc"
|
||||
t.KeyCtrlLeft = "\x1b[Od"
|
||||
}
|
||||
if t.KeyShfHome == "\x1b[7$" && t.KeyShfEnd == "\x1b[8$" {
|
||||
t.KeyCtrlHome = "\x1b[7^"
|
||||
t.KeyCtrlEnd = "\x1b[8^"
|
||||
}
|
||||
|
||||
// If the kmous entry is present, then we need to record the
|
||||
// the codes to enter and exit mouse mode. Sadly, this is not
|
||||
// part of the terminfo databases anywhere that I've found, but
|
||||
// is an extension. The escape codes are documented in the XTerm
|
||||
// manual, and all terminals that have kmous are expected to
|
||||
// use these same codes, unless explicitly configured otherwise
|
||||
// vi XM. Note that in any event, we only known how to parse either
|
||||
// x11 or SGR mouse events -- if your terminal doesn't support one
|
||||
// of these two forms, you maybe out of luck.
|
||||
t.MouseMode = tigetstr("XM")
|
||||
if t.Mouse != "" && t.MouseMode == "" {
|
||||
// we anticipate that all xterm mouse tracking compatible
|
||||
// terminals understand mouse tracking (1000), but we hope
|
||||
// that those that don't understand any-event tracking (1003)
|
||||
// will at least ignore it. Likewise we hope that terminals
|
||||
// that don't understand SGR reporting (1006) just ignore it.
|
||||
t.MouseMode = "%?%p1%{1}%=%t%'h'%Pa%e%'l'%Pa%;" +
|
||||
"\x1b[?1000%ga%c\x1b[?1003%ga%c\x1b[?1006%ga%c"
|
||||
}
|
||||
|
||||
// We only support colors in ANSI 8 or 256 color mode.
|
||||
if t.Colors < 8 || t.SetFg == "" {
|
||||
t.Colors = 0
|
||||
}
|
||||
if t.SetCursor == "" {
|
||||
return nil, errors.New("terminal not cursor addressable")
|
||||
}
|
||||
|
||||
// For padding, we lookup the pad char. If that isn't present,
|
||||
// and npc is *not* set, then we assume a null byte.
|
||||
t.PadChar = tigetstr("pad")
|
||||
if t.PadChar == "" {
|
||||
if !tigetflag("npc") {
|
||||
t.PadChar = "\u0000"
|
||||
}
|
||||
}
|
||||
|
||||
// For some terminals we fabricate a -truecolor entry, that may
|
||||
// not exist in terminfo.
|
||||
if addTrueColor {
|
||||
t.SetFgRGB = "\x1b[38;2;%p1%d;%p2%d;%p3%dm"
|
||||
t.SetBgRGB = "\x1b[48;2;%p1%d;%p2%d;%p3%dm"
|
||||
t.SetFgBgRGB = "\x1b[38;2;%p1%d;%p2%d;%p3%d;" +
|
||||
"48;2;%p4%d;%p5%d;%p6%dm"
|
||||
}
|
||||
|
||||
// For terminals that use "standard" SGR sequences, lets combine the
|
||||
// foreground and background together.
|
||||
if strings.HasPrefix(t.SetFg, "\x1b[") &&
|
||||
strings.HasPrefix(t.SetBg, "\x1b[") &&
|
||||
strings.HasSuffix(t.SetFg, "m") &&
|
||||
strings.HasSuffix(t.SetBg, "m") {
|
||||
fg := t.SetFg[:len(t.SetFg)-1]
|
||||
r := regexp.MustCompile("%p1")
|
||||
bg := r.ReplaceAllString(t.SetBg[2:], "%p2")
|
||||
t.SetFgBg = fg + ";" + bg
|
||||
}
|
||||
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func dotGoAddInt(w io.Writer, n string, i int) {
|
||||
if i == 0 {
|
||||
// initialized to 0, ignore
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, " %-13s %d,\n", n+":", i)
|
||||
}
|
||||
func dotGoAddStr(w io.Writer, n string, s string) {
|
||||
if s == "" {
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, " %-13s %q,\n", n+":", s)
|
||||
}
|
||||
|
||||
func dotGoAddArr(w io.Writer, n string, a []string) {
|
||||
if len(a) == 0 {
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, " %-13s []string{", n+":")
|
||||
did := false
|
||||
for _, b := range a {
|
||||
if did {
|
||||
fmt.Fprint(w, ", ")
|
||||
}
|
||||
did = true
|
||||
fmt.Fprintf(w, "%q", b)
|
||||
}
|
||||
fmt.Fprintln(w, "},")
|
||||
}
|
||||
|
||||
func dotGoHeader(w io.Writer) {
|
||||
fmt.Fprintf(w, "// Generated by %s (%s/%s) on %s.\n",
|
||||
os.Args[0],
|
||||
runtime.GOOS, runtime.GOARCH,
|
||||
time.Now().Format(time.UnixDate))
|
||||
fmt.Fprintln(w, "// DO NOT HAND-EDIT")
|
||||
fmt.Fprintln(w, "")
|
||||
fmt.Fprintln(w, "package tcell")
|
||||
fmt.Fprintln(w, "")
|
||||
fmt.Fprintln(w, "func init() {")
|
||||
}
|
||||
|
||||
func dotGoTrailer(w io.Writer) {
|
||||
fmt.Fprintln(w, "}")
|
||||
}
|
||||
|
||||
func dotGoInfo(w io.Writer, t *tcell.Terminfo) {
|
||||
fmt.Fprintln(w, " AddTerminfo(&Terminfo{")
|
||||
dotGoAddStr(w, "Name", t.Name)
|
||||
dotGoAddArr(w, "Aliases", t.Aliases)
|
||||
dotGoAddInt(w, "Columns", t.Columns)
|
||||
dotGoAddInt(w, "Lines", t.Lines)
|
||||
dotGoAddInt(w, "Colors", t.Colors)
|
||||
dotGoAddStr(w, "Bell", t.Bell)
|
||||
dotGoAddStr(w, "Clear", t.Clear)
|
||||
dotGoAddStr(w, "EnterCA", t.EnterCA)
|
||||
dotGoAddStr(w, "ExitCA", t.ExitCA)
|
||||
dotGoAddStr(w, "ShowCursor", t.ShowCursor)
|
||||
dotGoAddStr(w, "HideCursor", t.HideCursor)
|
||||
dotGoAddStr(w, "AttrOff", t.AttrOff)
|
||||
dotGoAddStr(w, "Underline", t.Underline)
|
||||
dotGoAddStr(w, "Bold", t.Bold)
|
||||
dotGoAddStr(w, "Dim", t.Dim)
|
||||
dotGoAddStr(w, "Blink", t.Blink)
|
||||
dotGoAddStr(w, "Reverse", t.Reverse)
|
||||
dotGoAddStr(w, "EnterKeypad", t.EnterKeypad)
|
||||
dotGoAddStr(w, "ExitKeypad", t.ExitKeypad)
|
||||
dotGoAddStr(w, "SetFg", t.SetFg)
|
||||
dotGoAddStr(w, "SetBg", t.SetBg)
|
||||
dotGoAddStr(w, "SetFgBg", t.SetFgBg)
|
||||
dotGoAddStr(w, "PadChar", t.PadChar)
|
||||
dotGoAddStr(w, "AltChars", t.AltChars)
|
||||
dotGoAddStr(w, "EnterAcs", t.EnterAcs)
|
||||
dotGoAddStr(w, "ExitAcs", t.ExitAcs)
|
||||
dotGoAddStr(w, "EnableAcs", t.EnableAcs)
|
||||
dotGoAddStr(w, "SetFgRGB", t.SetFgRGB)
|
||||
dotGoAddStr(w, "SetBgRGB", t.SetBgRGB)
|
||||
dotGoAddStr(w, "SetFgBgRGB", t.SetFgBgRGB)
|
||||
dotGoAddStr(w, "Mouse", t.Mouse)
|
||||
dotGoAddStr(w, "MouseMode", t.MouseMode)
|
||||
dotGoAddStr(w, "SetCursor", t.SetCursor)
|
||||
dotGoAddStr(w, "CursorBack1", t.CursorBack1)
|
||||
dotGoAddStr(w, "CursorUp1", t.CursorUp1)
|
||||
dotGoAddStr(w, "KeyUp", t.KeyUp)
|
||||
dotGoAddStr(w, "KeyDown", t.KeyDown)
|
||||
dotGoAddStr(w, "KeyRight", t.KeyRight)
|
||||
dotGoAddStr(w, "KeyLeft", t.KeyLeft)
|
||||
dotGoAddStr(w, "KeyInsert", t.KeyInsert)
|
||||
dotGoAddStr(w, "KeyDelete", t.KeyDelete)
|
||||
dotGoAddStr(w, "KeyBackspace", t.KeyBackspace)
|
||||
dotGoAddStr(w, "KeyHome", t.KeyHome)
|
||||
dotGoAddStr(w, "KeyEnd", t.KeyEnd)
|
||||
dotGoAddStr(w, "KeyPgUp", t.KeyPgUp)
|
||||
dotGoAddStr(w, "KeyPgDn", t.KeyPgDn)
|
||||
dotGoAddStr(w, "KeyF1", t.KeyF1)
|
||||
dotGoAddStr(w, "KeyF2", t.KeyF2)
|
||||
dotGoAddStr(w, "KeyF3", t.KeyF3)
|
||||
dotGoAddStr(w, "KeyF4", t.KeyF4)
|
||||
dotGoAddStr(w, "KeyF5", t.KeyF5)
|
||||
dotGoAddStr(w, "KeyF6", t.KeyF6)
|
||||
dotGoAddStr(w, "KeyF7", t.KeyF7)
|
||||
dotGoAddStr(w, "KeyF8", t.KeyF8)
|
||||
dotGoAddStr(w, "KeyF9", t.KeyF9)
|
||||
dotGoAddStr(w, "KeyF10", t.KeyF10)
|
||||
dotGoAddStr(w, "KeyF11", t.KeyF11)
|
||||
dotGoAddStr(w, "KeyF12", t.KeyF12)
|
||||
dotGoAddStr(w, "KeyF13", t.KeyF13)
|
||||
dotGoAddStr(w, "KeyF14", t.KeyF14)
|
||||
dotGoAddStr(w, "KeyF15", t.KeyF15)
|
||||
dotGoAddStr(w, "KeyF16", t.KeyF16)
|
||||
dotGoAddStr(w, "KeyF17", t.KeyF17)
|
||||
dotGoAddStr(w, "KeyF18", t.KeyF18)
|
||||
dotGoAddStr(w, "KeyF19", t.KeyF19)
|
||||
dotGoAddStr(w, "KeyF20", t.KeyF20)
|
||||
dotGoAddStr(w, "KeyF21", t.KeyF21)
|
||||
dotGoAddStr(w, "KeyF22", t.KeyF22)
|
||||
dotGoAddStr(w, "KeyF23", t.KeyF23)
|
||||
dotGoAddStr(w, "KeyF24", t.KeyF24)
|
||||
dotGoAddStr(w, "KeyF25", t.KeyF25)
|
||||
dotGoAddStr(w, "KeyF26", t.KeyF26)
|
||||
dotGoAddStr(w, "KeyF27", t.KeyF27)
|
||||
dotGoAddStr(w, "KeyF28", t.KeyF28)
|
||||
dotGoAddStr(w, "KeyF29", t.KeyF29)
|
||||
dotGoAddStr(w, "KeyF30", t.KeyF30)
|
||||
dotGoAddStr(w, "KeyF31", t.KeyF31)
|
||||
dotGoAddStr(w, "KeyF32", t.KeyF32)
|
||||
dotGoAddStr(w, "KeyF33", t.KeyF33)
|
||||
dotGoAddStr(w, "KeyF34", t.KeyF34)
|
||||
dotGoAddStr(w, "KeyF35", t.KeyF35)
|
||||
dotGoAddStr(w, "KeyF36", t.KeyF36)
|
||||
dotGoAddStr(w, "KeyF37", t.KeyF37)
|
||||
dotGoAddStr(w, "KeyF38", t.KeyF38)
|
||||
dotGoAddStr(w, "KeyF39", t.KeyF39)
|
||||
dotGoAddStr(w, "KeyF40", t.KeyF40)
|
||||
dotGoAddStr(w, "KeyF41", t.KeyF41)
|
||||
dotGoAddStr(w, "KeyF42", t.KeyF42)
|
||||
dotGoAddStr(w, "KeyF43", t.KeyF43)
|
||||
dotGoAddStr(w, "KeyF44", t.KeyF44)
|
||||
dotGoAddStr(w, "KeyF45", t.KeyF45)
|
||||
dotGoAddStr(w, "KeyF46", t.KeyF46)
|
||||
dotGoAddStr(w, "KeyF47", t.KeyF47)
|
||||
dotGoAddStr(w, "KeyF48", t.KeyF48)
|
||||
dotGoAddStr(w, "KeyF49", t.KeyF49)
|
||||
dotGoAddStr(w, "KeyF50", t.KeyF50)
|
||||
dotGoAddStr(w, "KeyF51", t.KeyF51)
|
||||
dotGoAddStr(w, "KeyF52", t.KeyF52)
|
||||
dotGoAddStr(w, "KeyF53", t.KeyF53)
|
||||
dotGoAddStr(w, "KeyF54", t.KeyF54)
|
||||
dotGoAddStr(w, "KeyF55", t.KeyF55)
|
||||
dotGoAddStr(w, "KeyF56", t.KeyF56)
|
||||
dotGoAddStr(w, "KeyF57", t.KeyF57)
|
||||
dotGoAddStr(w, "KeyF58", t.KeyF58)
|
||||
dotGoAddStr(w, "KeyF59", t.KeyF59)
|
||||
dotGoAddStr(w, "KeyF60", t.KeyF60)
|
||||
dotGoAddStr(w, "KeyF61", t.KeyF61)
|
||||
dotGoAddStr(w, "KeyF62", t.KeyF62)
|
||||
dotGoAddStr(w, "KeyF63", t.KeyF63)
|
||||
dotGoAddStr(w, "KeyF64", t.KeyF64)
|
||||
dotGoAddStr(w, "KeyCancel", t.KeyCancel)
|
||||
dotGoAddStr(w, "KeyPrint", t.KeyPrint)
|
||||
dotGoAddStr(w, "KeyExit", t.KeyExit)
|
||||
dotGoAddStr(w, "KeyHelp", t.KeyHelp)
|
||||
dotGoAddStr(w, "KeyClear", t.KeyClear)
|
||||
dotGoAddStr(w, "KeyBacktab", t.KeyBacktab)
|
||||
dotGoAddStr(w, "KeyShfLeft", t.KeyShfLeft)
|
||||
dotGoAddStr(w, "KeyShfRight", t.KeyShfRight)
|
||||
dotGoAddStr(w, "KeyShfUp", t.KeyShfUp)
|
||||
dotGoAddStr(w, "KeyShfDown", t.KeyShfDown)
|
||||
dotGoAddStr(w, "KeyCtrlLeft", t.KeyCtrlLeft)
|
||||
dotGoAddStr(w, "KeyCtrlRight", t.KeyCtrlRight)
|
||||
dotGoAddStr(w, "KeyCtrlUp", t.KeyCtrlUp)
|
||||
dotGoAddStr(w, "KeyCtrlDown", t.KeyCtrlDown)
|
||||
dotGoAddStr(w, "KeyMetaLeft", t.KeyMetaLeft)
|
||||
dotGoAddStr(w, "KeyMetaRight", t.KeyMetaRight)
|
||||
dotGoAddStr(w, "KeyMetaUp", t.KeyMetaUp)
|
||||
dotGoAddStr(w, "KeyMetaDown", t.KeyMetaDown)
|
||||
dotGoAddStr(w, "KeyAltLeft", t.KeyAltLeft)
|
||||
dotGoAddStr(w, "KeyAltRight", t.KeyAltRight)
|
||||
dotGoAddStr(w, "KeyAltUp", t.KeyAltUp)
|
||||
dotGoAddStr(w, "KeyAltDown", t.KeyAltDown)
|
||||
dotGoAddStr(w, "KeyAltShfLeft", t.KeyAltShfLeft)
|
||||
dotGoAddStr(w, "KeyAltShfRight", t.KeyAltShfRight)
|
||||
dotGoAddStr(w, "KeyAltShfUp", t.KeyAltShfUp)
|
||||
dotGoAddStr(w, "KeyAltShfDown", t.KeyAltShfDown)
|
||||
dotGoAddStr(w, "KeyMetaShfLeft", t.KeyMetaShfLeft)
|
||||
dotGoAddStr(w, "KeyMetaShfRight", t.KeyMetaShfRight)
|
||||
dotGoAddStr(w, "KeyMetaShfUp", t.KeyMetaShfUp)
|
||||
dotGoAddStr(w, "KeyMetaShfDown", t.KeyMetaShfDown)
|
||||
dotGoAddStr(w, "KeyCtrlShfLeft", t.KeyCtrlShfLeft)
|
||||
dotGoAddStr(w, "KeyCtrlShfRight", t.KeyCtrlShfRight)
|
||||
dotGoAddStr(w, "KeyCtrlShfUp", t.KeyCtrlShfUp)
|
||||
dotGoAddStr(w, "KeyCtrlShfDown", t.KeyCtrlShfDown)
|
||||
dotGoAddStr(w, "KeyShfHome", t.KeyShfHome)
|
||||
dotGoAddStr(w, "KeyShfEnd", t.KeyShfEnd)
|
||||
dotGoAddStr(w, "KeyCtrlHome", t.KeyCtrlHome)
|
||||
dotGoAddStr(w, "KeyCtrlEnd", t.KeyCtrlEnd)
|
||||
dotGoAddStr(w, "KeyMetaHome", t.KeyMetaHome)
|
||||
dotGoAddStr(w, "KeyMetaEnd", t.KeyMetaEnd)
|
||||
dotGoAddStr(w, "KeyAltHome", t.KeyAltHome)
|
||||
dotGoAddStr(w, "KeyAltEnd", t.KeyAltEnd)
|
||||
dotGoAddStr(w, "KeyCtrlShfHome", t.KeyCtrlShfHome)
|
||||
dotGoAddStr(w, "KeyCtrlShfEnd", t.KeyCtrlShfEnd)
|
||||
dotGoAddStr(w, "KeyMetaShfHome", t.KeyMetaShfHome)
|
||||
dotGoAddStr(w, "KeyMetaShfEnd", t.KeyMetaShfEnd)
|
||||
dotGoAddStr(w, "KeyAltShfHome", t.KeyAltShfHome)
|
||||
dotGoAddStr(w, "KeyAltShfEnd", t.KeyAltShfEnd)
|
||||
fmt.Fprintln(w, " })")
|
||||
}
|
||||
|
||||
func MkInfo() ([]byte, error) {
|
||||
jsonfile := ""
|
||||
gofile := ""
|
||||
nofatal := true
|
||||
quiet := true
|
||||
|
||||
var e error
|
||||
js := []byte{}
|
||||
|
||||
args := []string{os.Getenv("TERM")}
|
||||
|
||||
tdata := make(map[string]*tcell.Terminfo)
|
||||
adata := make(map[string]string)
|
||||
for _, term := range args {
|
||||
if arr := strings.SplitN(term, "=", 2); len(arr) == 2 {
|
||||
adata[arr[0]] = arr[1]
|
||||
} else if t, e := getinfo(term); e != nil {
|
||||
if !quiet {
|
||||
fmt.Fprintf(os.Stderr,
|
||||
"Failed loading %s: %v\n", term, e)
|
||||
}
|
||||
if !nofatal {
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
tdata[t.Name] = t
|
||||
}
|
||||
}
|
||||
for alias, canon := range adata {
|
||||
if t, ok := tdata[canon]; ok {
|
||||
t.Aliases = append(t.Aliases, alias)
|
||||
// sort aliases to avoid extra diffs
|
||||
sort.Strings(t.Aliases)
|
||||
} else {
|
||||
if !quiet {
|
||||
fmt.Fprintf(os.Stderr,
|
||||
"Alias %s missing canonical %s\n",
|
||||
alias, canon)
|
||||
}
|
||||
if !nofatal {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if gofile != "" {
|
||||
w := os.Stdout
|
||||
if gofile != "-" {
|
||||
if w, e = os.Create(gofile); e != nil {
|
||||
return []byte{}, fmt.Errorf("Failed: %v", e)
|
||||
}
|
||||
}
|
||||
dotGoHeader(w)
|
||||
for _, term := range args {
|
||||
if t := tdata[term]; t != nil {
|
||||
dotGoInfo(w, t)
|
||||
}
|
||||
}
|
||||
dotGoTrailer(w)
|
||||
if w != os.Stdout {
|
||||
w.Close()
|
||||
}
|
||||
} else if jsonfile != "" {
|
||||
w := os.Stdout
|
||||
if jsonfile != "-" {
|
||||
if w, e = os.Create(jsonfile); e != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed: %v", e)
|
||||
}
|
||||
}
|
||||
for _, term := range args {
|
||||
if t := tdata[term]; t != nil {
|
||||
js, e = json.Marshal(t)
|
||||
fmt.Fprintln(w, string(js))
|
||||
}
|
||||
// arguably if there is more than one term, this
|
||||
// should be a javascript array, but that's not how
|
||||
// we load it. We marshal objects one at a time from
|
||||
// the file.
|
||||
}
|
||||
if e != nil {
|
||||
return []byte{}, fmt.Errorf("Failed: %v", e)
|
||||
}
|
||||
} else {
|
||||
for _, term := range args {
|
||||
if t := tdata[term]; t != nil {
|
||||
js, e := json.Marshal(tdata[term])
|
||||
if e != nil {
|
||||
return []byte{}, fmt.Errorf("Failed ", e)
|
||||
}
|
||||
return js, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return []byte{}, nil
|
||||
}
|
||||
@@ -85,6 +85,30 @@ func LuaFunctionCommand(function string) func([]string) {
|
||||
}
|
||||
}
|
||||
|
||||
// LuaFunctionComplete returns a function which can be used for autocomplete in plugins
|
||||
func LuaFunctionComplete(function string) func(string) []string {
|
||||
return func(input string) (result []string) {
|
||||
|
||||
res, err := Call(function, input)
|
||||
if err != nil {
|
||||
TermMessage(err)
|
||||
}
|
||||
if tbl, ok := res.(*lua.LTable); !ok {
|
||||
TermMessage(function, "should return a table of strings")
|
||||
} else {
|
||||
for i := 1; i <= tbl.Len(); i++ {
|
||||
val := tbl.RawGetInt(i)
|
||||
if v, ok := val.(lua.LString); !ok {
|
||||
TermMessage(function, "should return a table of strings")
|
||||
} else {
|
||||
result = append(result, string(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
func LuaFunctionJob(function string) func(string, ...string) {
|
||||
return func(output string, args ...string) {
|
||||
_, err := Call(function, unpack(append([]string{output}, args...))...)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -125,8 +125,8 @@ func Search(searchStr string, v *View, down bool) {
|
||||
return
|
||||
}
|
||||
|
||||
v.Cursor.CurSelection[0] = FromCharPos(charPos+runePos(match[0], str), v.Buf)
|
||||
v.Cursor.CurSelection[1] = FromCharPos(charPos+runePos(match[1], str), v.Buf)
|
||||
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)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -9,6 +8,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/yosuke-furukawa/json5/encoding/json5"
|
||||
"github.com/zyedidia/glob"
|
||||
)
|
||||
|
||||
@@ -21,16 +21,21 @@ func InitGlobalSettings() {
|
||||
var parsed map[string]interface{}
|
||||
|
||||
filename := configDir + "/settings.json"
|
||||
writeSettings := false
|
||||
if _, e := os.Stat(filename); e == nil {
|
||||
input, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
TermMessage("Error reading settings.json file: " + err.Error())
|
||||
return
|
||||
}
|
||||
if !strings.HasPrefix(string(input), "null") {
|
||||
if err != nil {
|
||||
TermMessage("Error reading settings.json file: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(input, &parsed)
|
||||
if err != nil {
|
||||
TermMessage("Error reading settings.json:", err.Error())
|
||||
err = json5.Unmarshal(input, &parsed)
|
||||
if err != nil {
|
||||
TermMessage("Error reading settings.json:", err.Error())
|
||||
}
|
||||
} else {
|
||||
writeSettings = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +49,7 @@ func InitGlobalSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) || writeSettings {
|
||||
err := WriteSettings(filename)
|
||||
if err != nil {
|
||||
TermMessage("Error writing settings.json file: " + err.Error())
|
||||
@@ -65,7 +70,7 @@ func InitLocalSettings(buf *Buffer) {
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(input, &parsed)
|
||||
err = json5.Unmarshal(input, &parsed)
|
||||
if err != nil {
|
||||
TermMessage("Error reading settings.json:", err.Error())
|
||||
}
|
||||
@@ -92,31 +97,36 @@ func InitLocalSettings(buf *Buffer) {
|
||||
func WriteSettings(filename string) error {
|
||||
var err error
|
||||
if _, e := os.Stat(configDir); e == nil {
|
||||
var parsed map[string]interface{}
|
||||
parsed := make(map[string]interface{})
|
||||
|
||||
filename := configDir + "/settings.json"
|
||||
for k, v := range globalSettings {
|
||||
parsed[k] = v
|
||||
}
|
||||
if _, e := os.Stat(filename); e == nil {
|
||||
input, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if string(input) != "null" {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(input, &parsed)
|
||||
if err != nil {
|
||||
TermMessage("Error reading settings.json:", err.Error())
|
||||
}
|
||||
}
|
||||
err = json5.Unmarshal(input, &parsed)
|
||||
if err != nil {
|
||||
TermMessage("Error reading settings.json:", err.Error())
|
||||
}
|
||||
|
||||
for k, v := range parsed {
|
||||
if !strings.HasPrefix(reflect.TypeOf(v).String(), "map") {
|
||||
if _, ok := globalSettings[k]; ok {
|
||||
parsed[k] = globalSettings[k]
|
||||
for k, v := range parsed {
|
||||
if !strings.HasPrefix(reflect.TypeOf(v).String(), "map") {
|
||||
if _, ok := globalSettings[k]; ok {
|
||||
parsed[k] = globalSettings[k]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
txt, _ := json.MarshalIndent(parsed, "", " ")
|
||||
err = ioutil.WriteFile(filename, txt, 0644)
|
||||
txt, _ := json5.MarshalIndent(parsed, "", " ")
|
||||
err = ioutil.WriteFile(filename, append(txt, '\n'), 0644)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -156,9 +166,10 @@ func DefaultGlobalSettings() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"autoindent": true,
|
||||
"colorscheme": "zenburn",
|
||||
"cursorline": false,
|
||||
"cursorline": true,
|
||||
"ignorecase": false,
|
||||
"indentchar": " ",
|
||||
"infobar": true,
|
||||
"ruler": true,
|
||||
"savecursor": false,
|
||||
"saveundo": false,
|
||||
@@ -176,7 +187,7 @@ func DefaultGlobalSettings() map[string]interface{} {
|
||||
func DefaultLocalSettings() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"autoindent": true,
|
||||
"cursorline": false,
|
||||
"cursorline": true,
|
||||
"filetype": "Unknown",
|
||||
"ignorecase": false,
|
||||
"indentchar": " ",
|
||||
@@ -197,6 +208,12 @@ func DefaultLocalSettings() map[string]interface{} {
|
||||
// is local only it will set the local version
|
||||
// Use setlocal to force an option to be set locally
|
||||
func SetOption(option, value string) error {
|
||||
if option == "colorscheme" {
|
||||
if !ColorschemeExists(value) {
|
||||
return errors.New(value + " is not a valid colorscheme")
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := globalSettings[option]; !ok {
|
||||
if _, ok := CurView().Buf.Settings[option]; !ok {
|
||||
return errors.New("Invalid option")
|
||||
@@ -234,6 +251,12 @@ func SetOption(option, value string) error {
|
||||
}
|
||||
}
|
||||
|
||||
if option == "infobar" {
|
||||
for _, tab := range tabs {
|
||||
tab.Resize()
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := CurView().Buf.Settings[option]; ok {
|
||||
for _, tab := range tabs {
|
||||
for _, view := range tab.views {
|
||||
|
||||
@@ -146,9 +146,7 @@ func (s *SplitTree) ResizeSplits() {
|
||||
n.view.y = s.y + n.view.height*i
|
||||
n.view.x = s.x
|
||||
}
|
||||
// n.view.ToggleStatusLine()
|
||||
_, screenH := screen.Size()
|
||||
if n.view.Buf.Settings["statusline"].(bool) || (n.view.y+n.view.height) != screenH-1 {
|
||||
if n.view.Buf.Settings["statusline"].(bool) {
|
||||
n.view.height--
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,12 @@ func NewTabFromView(v *View) *Tab {
|
||||
|
||||
w, h := screen.Size()
|
||||
t.tree.width = w
|
||||
t.tree.height = h - 1
|
||||
t.tree.height = h
|
||||
|
||||
if globalSettings["infobar"].(bool) {
|
||||
t.tree.height--
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
@@ -49,7 +54,12 @@ func (t *Tab) Cleanup() {
|
||||
func (t *Tab) Resize() {
|
||||
w, h := screen.Size()
|
||||
t.tree.width = w
|
||||
t.tree.height = h - 1
|
||||
t.tree.height = h
|
||||
|
||||
if globalSettings["infobar"].(bool) {
|
||||
t.tree.height--
|
||||
}
|
||||
|
||||
t.tree.ResizeSplits()
|
||||
}
|
||||
|
||||
@@ -61,7 +71,7 @@ func CurView() *View {
|
||||
|
||||
// TabbarString returns the string that should be displayed in the tabbar
|
||||
// It also returns a map containing which indicies correspond to which tab number
|
||||
// This is useful when we know that the mouse click has occured at an x location
|
||||
// This is useful when we know that the mouse click has occurred at an x location
|
||||
// but need to know which tab that corresponds to to accurately change the tab
|
||||
func TabbarString() (string, map[int]int) {
|
||||
str := ""
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -20,8 +23,8 @@ func Count(s string) int {
|
||||
return utf8.RuneCountInString(s)
|
||||
}
|
||||
|
||||
// NumOccurences counts the number of occurences of a byte in a string
|
||||
func NumOccurences(s string, c byte) int {
|
||||
// NumOccurrences counts the number of occurences of a byte in a string
|
||||
func NumOccurrences(s string, c byte) int {
|
||||
var n int
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == c {
|
||||
@@ -154,7 +157,7 @@ func GetModTime(path string) (time.Time, bool) {
|
||||
// StringWidth returns the width of a string where tabs count as `tabsize` width
|
||||
func StringWidth(str string, tabsize int) int {
|
||||
sw := runewidth.StringWidth(str)
|
||||
sw += NumOccurences(str, '\t') * (tabsize - 1)
|
||||
sw += NumOccurrences(str, '\t') * (tabsize - 1)
|
||||
return sw
|
||||
}
|
||||
|
||||
@@ -182,6 +185,34 @@ func runePos(p int, str string) int {
|
||||
return utf8.RuneCountInString(str[:p])
|
||||
}
|
||||
|
||||
func lcs(a, b string) string {
|
||||
arunes := []rune(a)
|
||||
brunes := []rune(b)
|
||||
|
||||
lcs := ""
|
||||
for i, r := range arunes {
|
||||
if i >= len(brunes) {
|
||||
break
|
||||
}
|
||||
if r == brunes[i] {
|
||||
lcs += string(r)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return lcs
|
||||
}
|
||||
|
||||
func CommonSubstring(arr ...string) string {
|
||||
commonStr := arr[0]
|
||||
|
||||
for _, str := range arr[1:] {
|
||||
commonStr = lcs(commonStr, str)
|
||||
}
|
||||
|
||||
return commonStr
|
||||
}
|
||||
|
||||
// Abs is a simple absolute value function for ints
|
||||
func Abs(n int) int {
|
||||
if n < 0 {
|
||||
@@ -189,3 +220,77 @@ func Abs(n int) int {
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// FuncName returns the name of a given function object
|
||||
func FuncName(i interface{}) string {
|
||||
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
||||
}
|
||||
|
||||
// SplitCommandArgs seperates multiple command arguments which may be quoted.
|
||||
// The returned slice contains at least one string
|
||||
func SplitCommandArgs(input string) []string {
|
||||
var result []string
|
||||
curArg := new(bytes.Buffer)
|
||||
inQuote := false
|
||||
escape := false
|
||||
|
||||
appendResult := func() {
|
||||
str := curArg.String()
|
||||
inQuote = false
|
||||
escape = false
|
||||
if strings.HasPrefix(str, `"`) && strings.HasSuffix(str, `"`) {
|
||||
if unquoted, err := strconv.Unquote(str); err == nil {
|
||||
str = unquoted
|
||||
}
|
||||
}
|
||||
result = append(result, str)
|
||||
curArg.Reset()
|
||||
}
|
||||
|
||||
for _, r := range input {
|
||||
if r == ' ' && !inQuote {
|
||||
appendResult()
|
||||
} else {
|
||||
curArg.WriteRune(r)
|
||||
|
||||
if r == '"' && !inQuote {
|
||||
inQuote = true
|
||||
} else {
|
||||
if inQuote && !escape {
|
||||
if r == '"' {
|
||||
inQuote = false
|
||||
}
|
||||
if r == '\\' {
|
||||
escape = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
escape = false
|
||||
}
|
||||
appendResult()
|
||||
return result
|
||||
}
|
||||
|
||||
// JoinCommandArgs joins multiple command arguments and quote the strings if needed.
|
||||
func JoinCommandArgs(args ...string) string {
|
||||
buf := new(bytes.Buffer)
|
||||
first := true
|
||||
for _, arg := range args {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
buf.WriteRune(' ')
|
||||
}
|
||||
quoted := strconv.Quote(arg)
|
||||
if quoted[1:len(quoted)-1] != arg || strings.ContainsRune(arg, ' ') {
|
||||
buf.WriteString(quoted)
|
||||
} else {
|
||||
buf.WriteString(arg)
|
||||
}
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNumOccurences(t *testing.T) {
|
||||
var tests = []struct {
|
||||
@@ -13,7 +16,7 @@ func TestNumOccurences(t *testing.T) {
|
||||
{"∆ƒ\tø ® \t\t", '\t', 3},
|
||||
}
|
||||
for _, test := range tests {
|
||||
if got := NumOccurences(test.inputStr, test.inputChar); got != test.want {
|
||||
if got := NumOccurrences(test.inputStr, test.inputChar); got != test.want {
|
||||
t.Errorf("NumOccurences(%s, %c) = %d", test.inputStr, test.inputChar, got)
|
||||
}
|
||||
}
|
||||
@@ -63,3 +66,48 @@ func TestIsWordChar(t *testing.T) {
|
||||
t.Errorf("IsWordChar(\n)) = true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJoinAndSplitCommandArgs(t *testing.T) {
|
||||
tests := []struct {
|
||||
Query []string
|
||||
Wanted string
|
||||
}{
|
||||
{[]string{`test case`}, `"test case"`},
|
||||
{[]string{`quote "test"`}, `"quote \"test\""`},
|
||||
{[]string{`slash\\\ test`}, `"slash\\\\\\ test"`},
|
||||
{[]string{`path 1`, `path\" 2`}, `"path 1" "path\\\" 2"`},
|
||||
{[]string{`foo`}, `foo`},
|
||||
{[]string{`foo\"bar`}, `"foo\\\"bar"`},
|
||||
{[]string{``}, ``},
|
||||
{[]string{`"`}, `"\""`},
|
||||
{[]string{`a`, ``}, `a `},
|
||||
{[]string{``, ``, ``, ``}, ` `},
|
||||
{[]string{"\n"}, `"\n"`},
|
||||
{[]string{"foo\tbar"}, `"foo\tbar"`},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
if result := JoinCommandArgs(test.Query...); test.Wanted != result {
|
||||
t.Errorf("JoinCommandArgs failed at Test %d\nGot: %q", i, result)
|
||||
}
|
||||
|
||||
if result := SplitCommandArgs(test.Wanted); !reflect.DeepEqual(test.Query, result) {
|
||||
t.Errorf("SplitCommandArgs failed at Test %d\nGot: `%q`", i, result)
|
||||
}
|
||||
}
|
||||
|
||||
splitTests := []struct {
|
||||
Query string
|
||||
Wanted []string
|
||||
}{
|
||||
{`"hallo""Welt"`, []string{`"hallo""Welt"`}},
|
||||
{`\"`, []string{`\"`}},
|
||||
{`"\"`, []string{`"\"`}},
|
||||
}
|
||||
|
||||
for i, test := range splitTests {
|
||||
if result := SplitCommandArgs(test.Query); !reflect.DeepEqual(test.Wanted, result) {
|
||||
t.Errorf("SplitCommandArgs failed at Split-Test %d\nGot: `%q`", i, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ type View struct {
|
||||
// NewView returns a new fullscreen view
|
||||
func NewView(buf *Buffer) *View {
|
||||
screenW, screenH := screen.Size()
|
||||
return NewViewWidthHeight(buf, screenW, screenH-1)
|
||||
return NewViewWidthHeight(buf, screenW, screenH)
|
||||
}
|
||||
|
||||
// NewViewWidthHeight returns a new view with the specified width and height
|
||||
@@ -145,6 +145,20 @@ func (v *View) ToggleTabbar() {
|
||||
}
|
||||
}
|
||||
|
||||
func (v *View) paste(clip string) {
|
||||
leadingWS := GetLeadingWhitespace(v.Buf.Line(v.Cursor.Y))
|
||||
|
||||
if v.Cursor.HasSelection() {
|
||||
v.Cursor.DeleteSelection()
|
||||
v.Cursor.ResetSelection()
|
||||
}
|
||||
clip = strings.Replace(clip, "\n", "\n"+leadingWS, -1)
|
||||
v.Buf.Insert(v.Cursor.Loc, clip)
|
||||
v.Cursor.Loc = v.Cursor.Loc.Move(Count(clip), v.Buf)
|
||||
v.freshClip = false
|
||||
messenger.Message("Pasted clipboard")
|
||||
}
|
||||
|
||||
// ScrollUp scrolls the view up n lines (if possible)
|
||||
func (v *View) ScrollUp(n int) {
|
||||
// Try to scroll by n but if it would overflow, scroll by 1
|
||||
@@ -169,15 +183,15 @@ func (v *View) ScrollDown(n int) {
|
||||
// If there are unsaved changes, the user will be asked if the view can be closed
|
||||
// causing them to lose the unsaved changes
|
||||
// The message is what to print after saying "You have unsaved changes. "
|
||||
func (v *View) CanClose(msg string) bool {
|
||||
func (v *View) CanClose() bool {
|
||||
if v.Buf.IsModified {
|
||||
quit, canceled := messenger.Prompt("You have unsaved changes. "+msg, "Unsaved", NoCompletion)
|
||||
char, canceled := messenger.LetterPrompt("Save changes to "+v.Buf.Name+" before closing? (y,n,esc) ", 'y', 'n')
|
||||
if !canceled {
|
||||
if strings.ToLower(quit) == "yes" || strings.ToLower(quit) == "y" {
|
||||
return true
|
||||
} else if strings.ToLower(quit) == "save" || strings.ToLower(quit) == "s" {
|
||||
if char == 'y' {
|
||||
v.Save(true)
|
||||
return true
|
||||
} else if char == 'n' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -217,7 +231,7 @@ func (v *View) CloseBuffer() {
|
||||
|
||||
// ReOpen reloads the current buffer
|
||||
func (v *View) ReOpen() {
|
||||
if v.CanClose("Continue? (yes, no, save) ") {
|
||||
if v.CanClose() {
|
||||
screen.Clear()
|
||||
v.Buf.ReOpen()
|
||||
v.Relocate()
|
||||
@@ -326,6 +340,10 @@ func (v *View) HandleEvent(event tcell.Event) {
|
||||
TermMessage(err)
|
||||
}
|
||||
}
|
||||
|
||||
if recordingMacro {
|
||||
curMacro = append(curMacro, e.Rune())
|
||||
}
|
||||
} else {
|
||||
for key, actions := range bindings {
|
||||
if e.Key() == key.keyCode {
|
||||
@@ -338,13 +356,36 @@ func (v *View) HandleEvent(event tcell.Event) {
|
||||
relocate = false
|
||||
for _, action := range actions {
|
||||
relocate = action(v, true) || relocate
|
||||
funcName := FuncName(action)
|
||||
if funcName != "main.(*View).ToggleMacro" && funcName != "main.(*View).PlayMacro" {
|
||||
if recordingMacro {
|
||||
curMacro = append(curMacro, action)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case *tcell.EventPaste:
|
||||
relocate = v.Paste(true)
|
||||
if !PreActionCall("Paste", v) {
|
||||
break
|
||||
}
|
||||
|
||||
leadingWS := GetLeadingWhitespace(v.Buf.Line(v.Cursor.Y))
|
||||
|
||||
if v.Cursor.HasSelection() {
|
||||
v.Cursor.DeleteSelection()
|
||||
v.Cursor.ResetSelection()
|
||||
}
|
||||
clip := e.Text()
|
||||
clip = strings.Replace(clip, "\n", "\n"+leadingWS, -1)
|
||||
v.Buf.Insert(v.Cursor.Loc, clip)
|
||||
v.Cursor.Loc = v.Cursor.Loc.Move(Count(clip), v.Buf)
|
||||
v.freshClip = false
|
||||
messenger.Message("Pasted clipboard")
|
||||
|
||||
PostActionCall("Paste", v)
|
||||
case *tcell.EventMouse:
|
||||
x, y := e.Position()
|
||||
x -= v.lineNumOffset - v.leftCol + v.x
|
||||
@@ -394,9 +435,13 @@ func (v *View) HandleEvent(event tcell.Event) {
|
||||
} else if v.doubleClick {
|
||||
v.Cursor.AddWordToSelection()
|
||||
} else {
|
||||
v.Cursor.CurSelection[1] = v.Cursor.Loc
|
||||
v.Cursor.SetSelectionEnd(v.Cursor.Loc)
|
||||
}
|
||||
}
|
||||
case tcell.Button2:
|
||||
// Middle mouse button was clicked,
|
||||
// We should paste primary
|
||||
v.PastePrimary(true)
|
||||
case tcell.ButtonNone:
|
||||
// Mouse event with no click
|
||||
if !v.mouseReleased {
|
||||
@@ -410,7 +455,7 @@ func (v *View) HandleEvent(event tcell.Event) {
|
||||
|
||||
if !v.doubleClick && !v.tripleClick {
|
||||
v.MoveToMouseClick(x, y)
|
||||
v.Cursor.CurSelection[1] = v.Cursor.Loc
|
||||
v.Cursor.SetSelectionEnd(v.Cursor.Loc)
|
||||
}
|
||||
v.mouseReleased = true
|
||||
}
|
||||
@@ -600,7 +645,7 @@ func (v *View) DisplayView() {
|
||||
lineNumStyle = style
|
||||
}
|
||||
if style, ok := colorscheme["current-line-number"]; ok {
|
||||
if curLineN == v.Cursor.Y {
|
||||
if curLineN == v.Cursor.Y && tabs[curTab].curView == v.Num && !v.Cursor.HasSelection() {
|
||||
lineNumStyle = style
|
||||
}
|
||||
}
|
||||
|
||||
19
runtime/colorschemes/bubblegum.micro
Normal file
19
runtime/colorschemes/bubblegum.micro
Normal file
@@ -0,0 +1,19 @@
|
||||
color-link default "241,231"
|
||||
color-link comment "246,231"
|
||||
color-link constant "130,231"
|
||||
color-link constant.string "136,231"
|
||||
color-link constant.number "131,231"
|
||||
color-link identifier "133,231"
|
||||
color-link statement "32,231"
|
||||
color-link preproc "28,231"
|
||||
color-link type "61,231"
|
||||
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 gutter-error "197,231"
|
||||
color-link gutter-warning "134,231"
|
||||
color-link line-number "246,254"
|
||||
color-link cursor-line "254"
|
||||
@@ -1,16 +1,20 @@
|
||||
color-link comment "blue"
|
||||
color-link constant "red"
|
||||
color-link identifier "cyan"
|
||||
color-link statement "yellow"
|
||||
color-link preproc "magenta"
|
||||
color-link type "green"
|
||||
color-link special "magenta"
|
||||
color-link ignore "default"
|
||||
color-link error ",brightred"
|
||||
color-link todo ",brightyellow"
|
||||
color-link indent-char "black"
|
||||
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"
|
||||
color-link default "188,237"
|
||||
color-link comment "108,237"
|
||||
color-link constant.string "174,237"
|
||||
color-link constant.number "116,237"
|
||||
color-link constant "181,237"
|
||||
color-link identifier "223,237"
|
||||
color-link statement "223,237"
|
||||
color-link preproc "223,237"
|
||||
color-link type "187,237"
|
||||
color-link special "181,237"
|
||||
color-link underlined "188,237"
|
||||
color-link error "115,236"
|
||||
color-link todo "bold 254,237"
|
||||
color-link statusline "186,236"
|
||||
color-link indent-char "238,237"
|
||||
color-link line-number "188,238"
|
||||
color-link gutter-error "237,174"
|
||||
color-link gutter-warning "174,237"
|
||||
color-link cursor-line "238"
|
||||
color-link current-line-number "188,237"
|
||||
|
||||
16
runtime/colorschemes/simple.micro
Normal file
16
runtime/colorschemes/simple.micro
Normal file
@@ -0,0 +1,16 @@
|
||||
color-link comment "blue"
|
||||
color-link constant "red"
|
||||
color-link identifier "cyan"
|
||||
color-link statement "yellow"
|
||||
color-link preproc "magenta"
|
||||
color-link type "green"
|
||||
color-link special "magenta"
|
||||
color-link ignore "default"
|
||||
color-link error ",brightred"
|
||||
color-link todo ",brightyellow"
|
||||
color-link indent-char "black"
|
||||
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"
|
||||
@@ -13,7 +13,7 @@ color-link error "115,236"
|
||||
color-link todo "bold 254,237"
|
||||
color-link statusline "186,236"
|
||||
color-link indent-char "238,237"
|
||||
color-link line-number "188,238"
|
||||
color-link line-number "248,238"
|
||||
color-link gutter-error "237,174"
|
||||
color-link gutter-warning "174,237"
|
||||
color-link cursor-line "238"
|
||||
|
||||
@@ -9,9 +9,13 @@ This help page aims to cover two aspects of micro's syntax highlighting engine:
|
||||
|
||||
Micro comes with a number of colorschemes by default. Here is the list:
|
||||
|
||||
* default: this is the simplest colorscheme. It uses 16 colors which are
|
||||
* simple: this is the simplest colorscheme. It uses 16 colors which are
|
||||
set by your terminal
|
||||
|
||||
* zenburn: this is micro's default colorscheme because it looks very good
|
||||
and works in 256 color terminals.
|
||||
this colorscheme also has the name 'default'
|
||||
|
||||
* solarized: this is the solarized colorscheme.
|
||||
You should have the solarized color palette in your terminal to use it.
|
||||
|
||||
@@ -19,8 +23,8 @@ Micro comes with a number of colorschemes by default. Here is the list:
|
||||
make sure your terminal supports true color before using it and that the
|
||||
MICRO_TRUECOLOR environment variable is set to 1 before starting micro.
|
||||
|
||||
* monokai: this is the monokai colorscheme and is micro's default colorscheme
|
||||
(as well as sublime text's). It requires true color to
|
||||
* 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.
|
||||
|
||||
* atom-dark-tc: this colorscheme is based off of Atom's "dark" colorscheme.
|
||||
|
||||
@@ -21,6 +21,8 @@ Here are the possible commands that you can use.
|
||||
* `setlocal option value`: sets the option to value locally (only in the current
|
||||
buffer).
|
||||
|
||||
* `show option`: shows the current value of the given option.
|
||||
|
||||
* `run sh-command`: runs the given shell command in the background. The
|
||||
command's output will be displayed in one line when it finishes running.
|
||||
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
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.
|
||||
|
||||
*Press CtrlQ to quit, and CtrlS to save.*
|
||||
|
||||
If you want to see all the keybindings press CtrlE and type `help keybindings`.
|
||||
|
||||
See the next section for more information about documentation and help.
|
||||
|
||||
### Accessing more help
|
||||
|
||||
Micro has a built-in help system much like Vim's (although less extensive).
|
||||
@@ -12,6 +18,7 @@ Typing help followed by nothing will open this page.
|
||||
|
||||
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
|
||||
* commands: Gives a list of all the commands and what they do
|
||||
* options: Gives a list of all the options you can customize
|
||||
@@ -21,15 +28,6 @@ Here are the possible help topics that you can read:
|
||||
|
||||
For example to open the help page on plugins you would press CtrlE and type `help plugins`.
|
||||
|
||||
### Usage
|
||||
|
||||
Once you have built the editor, simply start it by running
|
||||
`micro path/to/file.txt` or simply `micro` to open an empty buffer.
|
||||
|
||||
Micro also supports creating buffers from stdin:
|
||||
|
||||
```
|
||||
$ ifconfig | micro
|
||||
```
|
||||
|
||||
You can move the cursor around with the arrow keys and mouse.
|
||||
I recommend looking at the `tutorial` help file because it is short for each section and
|
||||
gives concrete examples of how to use the various configuration options in micro. However,
|
||||
it does not give the in-depth documentation that the other topics provide.
|
||||
|
||||
@@ -45,11 +45,13 @@ you can rebind them to your liking.
|
||||
"CtrlD": "DuplicateLine",
|
||||
"CtrlV": "Paste",
|
||||
"CtrlA": "SelectAll",
|
||||
"CtrlT": "AddTab"
|
||||
"CtrlT": "AddTab",
|
||||
"CtrlRightSq": "PreviousTab",
|
||||
"CtrlBackslash": "NextTab",
|
||||
"Home": "Start",
|
||||
"End": "End",
|
||||
"CtrlHome": "CursorStart",
|
||||
"CtrlEnd": "CursorEnd",
|
||||
"PageUp": "CursorPageUp",
|
||||
"PageDown": "CursorPageDown",
|
||||
"CtrlG": "ToggleHelp",
|
||||
@@ -61,6 +63,8 @@ you can rebind them to your liking.
|
||||
"CtrlQ": "Quit",
|
||||
"CtrlE": "CommandMode",
|
||||
"CtrlW": "NextSplit",
|
||||
"CtrlU": "ToggleMacro",
|
||||
"CtrlJ": "PlayMacro",
|
||||
|
||||
// Emacs-style keybindings
|
||||
"Alt-f": "WordRight",
|
||||
@@ -136,6 +140,7 @@ InsertNewline
|
||||
InsertSpace
|
||||
Backspace
|
||||
Delete
|
||||
Center
|
||||
InsertTab
|
||||
Save
|
||||
Find
|
||||
@@ -168,11 +173,14 @@ ClearStatus
|
||||
ShellMode
|
||||
CommandMode
|
||||
Quit
|
||||
QuitAll
|
||||
AddTab
|
||||
PreviousTab
|
||||
NextTab
|
||||
NextSplit
|
||||
PreviousSplit
|
||||
ToggleMacro
|
||||
PlayMacro
|
||||
```
|
||||
|
||||
Here is the list of all possible keys you can bind:
|
||||
|
||||
@@ -20,21 +20,8 @@ Here are the options that you can set:
|
||||
~/.config/micro/colorschemes/ directory. Micro comes by default with three
|
||||
colorschemes:
|
||||
|
||||
* default: this is the default colorscheme.
|
||||
|
||||
* solarized: this is the solarized colorscheme (used in the screenshot).
|
||||
You should have the solarized color palette in your terminal to use it.
|
||||
|
||||
* solarized-tc: this is the solarized colorscheme for true color, just
|
||||
make sure your terminal supports true color before using it and that the
|
||||
MICRO_TRUECOLOR environment variable is set to 1 before starting micro.
|
||||
|
||||
* monokai-tc: this is the monokai colorscheme. It requires true color to
|
||||
look perfect, but the 256 color approximation looks good as well.
|
||||
|
||||
* atom-dark-tc: this colorscheme is based off of Atom's "dark" colorscheme.
|
||||
It requires true color to look good.
|
||||
|
||||
You can read more about micro's colorschemes in the `colors` help topic
|
||||
(`help colors`).
|
||||
|
||||
* `tabsize`: sets the tab size to `option`
|
||||
|
||||
@@ -44,6 +31,11 @@ Here are the options that you can set:
|
||||
|
||||
default value: ` `
|
||||
|
||||
* `infobar`: enables the line at the bottom of the editor where messages are printed.
|
||||
This option is `global only`.
|
||||
|
||||
default value: `on`
|
||||
|
||||
* `filetype`: sets the filetype for the current buffer. This setting is `local only`
|
||||
|
||||
default value: this will be automatically set depending on the file you have open
|
||||
@@ -68,7 +60,7 @@ Here are the options that you can set:
|
||||
* `cursorline`: highlight the line that the cursor is on in a different color
|
||||
(the color is defined by the colorscheme you are using)
|
||||
|
||||
default value: `off`
|
||||
default value: `on`
|
||||
|
||||
* `ruler`: display line numbers
|
||||
|
||||
@@ -136,16 +128,16 @@ In the `settings.json` file you can also put set options locally by specifying a
|
||||
Here is an example which has `tabstospaces` on for all files except Go files, and
|
||||
`tabsize` 4 for all files except Ruby files:
|
||||
|
||||
```
|
||||
```json
|
||||
{
|
||||
"*.go": {
|
||||
"tabstospaces": false
|
||||
},
|
||||
"*.rb": {
|
||||
"tabsize": 2
|
||||
}
|
||||
},
|
||||
"tabstospaces": true,
|
||||
"tabsize": 4,
|
||||
"tabsize": 4
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ for example turning off `tabstospaces` only for Go files when they are opened.
|
||||
---
|
||||
|
||||
There are a number of functions and variables that are available to you in
|
||||
oder to access the inner workings of micro. Here is a list (the type signatures
|
||||
order to access the inner workings of micro. Here is a list (the type signatures
|
||||
for functions are given using Go's type system):
|
||||
|
||||
* `OS`: variable which gives the OS micro is currently running on (this is the same
|
||||
@@ -66,6 +66,9 @@ as Go's GOOS variable, so `darwin`, `windows`, `linux`, `freebsd`...)
|
||||
creates a command with `name` which will call `function` when executed.
|
||||
Use 0 for completions to get NoCompletion.
|
||||
|
||||
* `MakeCompletion(function string)`:
|
||||
creates a `Completion` to use with `MakeCommand`.
|
||||
|
||||
* `CurView()`: returns the current view
|
||||
|
||||
* `HandleCommand(cmd string)`: runs the given command
|
||||
@@ -104,6 +107,36 @@ The possible methods which you can call using the `messenger` variable are:
|
||||
|
||||
If you want a standard prompt, just use `messenger.Prompt(prompt, "", 0)`
|
||||
|
||||
# Autocomplete command arguments
|
||||
|
||||
See this example to learn how to use `MakeCompletion` and `MakeCommand`
|
||||
|
||||
```lua
|
||||
local function StartsWith(String,Start)
|
||||
String = String:upper()
|
||||
Start = Start:upper()
|
||||
return string.sub(String,1,string.len(Start))==Start
|
||||
end
|
||||
|
||||
function complete(input)
|
||||
local allCompletions = {"Hello", "World", "Foo", "Bar"}
|
||||
local result = {}
|
||||
|
||||
for i,v in pairs(allCompletions) do
|
||||
if StartsWith(v, input) then
|
||||
table.insert(result, v)
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function foo(arg)
|
||||
messenger:Message(arg)
|
||||
end
|
||||
|
||||
MakeCommand("foo", "example.foo", MakeCompletion("example.complete"))
|
||||
```
|
||||
|
||||
# Default plugins
|
||||
|
||||
For examples of plugins, see the default plugins `linter`, `go`, and `autoclose`.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Tutorial
|
||||
|
||||
This is a brief intro to micro's configuration system that will will give some
|
||||
simple examples showing how to configure settings, rebind keys,
|
||||
This is a brief intro to micro's configuration system that will give some
|
||||
simple examples showing how to configure settings, rebind keys,
|
||||
and use `init.lua` to configure micro to your liking.
|
||||
|
||||
Hopefully you'll find this useful.
|
||||
@@ -68,13 +68,13 @@ what actions are available, see the `keybindings` help topic (`> help keybinding
|
||||
|
||||
If you need more power than the json files provide, you can use the `init.lua`
|
||||
file. Create it in `~/.config/micro`. This file is a lua file that is run
|
||||
when micro starts and is essential a one-file plugin.
|
||||
when micro starts and is essentially a one-file plugin.
|
||||
|
||||
I'll show you how to use the `init.lua` file by giving an example of how to
|
||||
create a binding to `CtrlR` which will execute `go run` on the current file,
|
||||
given that the current file is a Go file.
|
||||
|
||||
You can do that by puttint the following in `init.lua`:
|
||||
You can do that by putting the following in `init.lua`:
|
||||
|
||||
```lua
|
||||
function gorun()
|
||||
|
||||
@@ -2,10 +2,14 @@ if GetOption("linter") == nil then
|
||||
AddOption("linter", true)
|
||||
end
|
||||
|
||||
MakeCommand("lint", "linter.runLinter", 0)
|
||||
MakeCommand("lint", "linter.lintCommand", 0)
|
||||
|
||||
function lintCommand()
|
||||
CurView():Save(false)
|
||||
runLinter()
|
||||
end
|
||||
|
||||
function runLinter()
|
||||
CurView():Save(false)
|
||||
local ft = CurView().Buf:FileType()
|
||||
local file = CurView().Buf.Path
|
||||
local devnull = "/dev/null"
|
||||
|
||||
@@ -8,8 +8,6 @@ Micro syntax files are almost identical to Nano's, except for some key differenc
|
||||
|
||||
* 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) ".*"`
|
||||
* Micro does not support `start="..." end="..."`. Instead use the `s` flag to match newlines and put `.*?` in the middle
|
||||
* For example `color green start="hello" end="world"` would become `color green (s) "hello.*?world"`
|
||||
|
||||
# Using with colorschemes
|
||||
|
||||
@@ -29,6 +27,7 @@ Here is a list of the files that have been converted to properly use colorscheme
|
||||
* rust
|
||||
* java
|
||||
* javascript
|
||||
* pascal
|
||||
* python
|
||||
* ruby
|
||||
* sh
|
||||
|
||||
@@ -1,17 +1,93 @@
|
||||
## Here is an example for assembler.
|
||||
##
|
||||
## Made by Nickolay Ilyushin <nickolay02@inbox.ru>. Next line is from previous (first) version (no need for modifications :P)
|
||||
syntax "asm" "\.(S|s|asm)$"
|
||||
color red "\<[A-Z_]{2,}\>"
|
||||
color brightgreen "\.(data|subsection|text)"
|
||||
color green "\.(align|file|globl|global|hidden|section|size|type|weak)"
|
||||
color brightyellow "\.(ascii|asciz|byte|double|float|hword|int|long|short|single|struct|word)"
|
||||
brightred (i) "^[[:space:]]*[.0-9A-Z_]*:"
|
||||
color brightcyan "^[[:space:]]*#[[:space:]]*(define|undef|include|ifn?def|endif|elif|else|if|warning|error)"
|
||||
## Highlight strings (note: VERY resource intensive)
|
||||
color brightyellow "<[^= ]*>" ""(\\.|[^"])*""
|
||||
color brightyellow start=""(\\.|[^"])*\\[[:space:]]*$" end="^(\\.|[^"])*""
|
||||
## Highlight comments
|
||||
color brightblue "//.*"
|
||||
color brightblue start="/\*" end="\*/"
|
||||
## Highlight trailing whitespace
|
||||
color ,green "[[:space:]]+$"
|
||||
|
||||
# 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 ";.*"
|
||||
|
||||
13
runtime/syntax/caddyfile.micro
Normal file
13
runtime/syntax/caddyfile.micro
Normal file
@@ -0,0 +1,13 @@
|
||||
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:]]+$"
|
||||
@@ -3,8 +3,8 @@
|
||||
syntax "conf" "\.c[o]?nf$"
|
||||
## Possible errors and parameters
|
||||
## Strings
|
||||
white (i) ""(\\.|[^"])*""
|
||||
color constant.string (i) ""(\\.|[^"])*""
|
||||
## Comments
|
||||
brightblue (i) "^[[:space:]]*#.*$"
|
||||
cyan (i) "^[[:space:]]*##.*$"
|
||||
color comment (i) "^[[:space:]]*#.*$"
|
||||
color comment (i) "^[[:space:]]*##.*$"
|
||||
|
||||
|
||||
@@ -11,6 +11,12 @@ color special "!important"
|
||||
color identifier ":active|:focus|:hover|:link|:visited|:link|:after|:before|$"
|
||||
color special "(\{|\}|\(|\)|\;|:|\]|~|<|>|,)"
|
||||
|
||||
# SCSS Varaibles
|
||||
color identifier (i) "\$\{?[0-9A-Z_!@#$*?-]+\}?"
|
||||
|
||||
# SCSS Commands
|
||||
color statement "@import|@mixin|@extend"
|
||||
|
||||
# Strings
|
||||
color constant ""(\\.|[^"])*""
|
||||
color constant "'(\\.|[^'])*'"
|
||||
|
||||
19
runtime/syntax/dart.micro
Normal file
19
runtime/syntax/dart.micro
Normal file
@@ -0,0 +1,19 @@
|
||||
syntax "dart" "\.dart$"
|
||||
|
||||
color constant.number "\b[-+]?([1-9][0-9]*|0[0-7]*|0x[0-9a-fA-F]+)([uU][lL]?|[lL][uU]?)?\b"
|
||||
color constant.number "\b[-+]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([EePp][+-]?[0-9]+)?[fFlL]?"
|
||||
color constant.number "\b[-+]?([0-9]+[EePp][+-]?[0-9]+)[fFlL]?"
|
||||
color identifier "[A-Za-z_][A-Za-z0-9_]*[[:space:]]*[(]"
|
||||
color statement "\b(break|case|catch|continue|default|else|finally)\b"
|
||||
color statement "\b(for|function|get|if|in|as|is|new|return|set|switch|final|await|async|sync)\b"
|
||||
color statement "\b(switch|this|throw|try|var|void|while|with|import|library|part|const|export)\b"
|
||||
color constant "\b(true|false|null)\b"
|
||||
color type "\b(List|String)\b"
|
||||
color type "\b(int|num|double|bool)\b"
|
||||
color statement "[-+/*=<>!~%?:&|]"
|
||||
color constant "/[^*]([^/]|(\\/))*[^\\]/[gim]*"
|
||||
color constant "\\[0-7][0-7]?[0-7]?|\\x[0-9a-fA-F]+|\\[bfnrt'"\?\\]"
|
||||
color comment "(^|[[:space:]])//.*"
|
||||
color comment "/\*.+\*/"
|
||||
color todo "TODO:?"
|
||||
color constant.string ""(\\.|[^"])*"|'(\\.|[^'])*'"
|
||||
@@ -2,29 +2,27 @@
|
||||
##
|
||||
syntax "ebuild" "\.e(build|class)$"
|
||||
## All the standard portage functions
|
||||
color brightgreen "^src_(unpack|compile|install|test)" "^pkg_(config|nofetch|setup|(pre|post)(inst|rm))"
|
||||
color identifier "^src_(unpack|compile|install|test)" "^pkg_(config|nofetch|setup|(pre|post)(inst|rm))"
|
||||
## Highlight bash related syntax
|
||||
color green "\<(case|do|done|elif|else|esac|exit|fi|for|function|if|in|local|read|return|select|shift|then|time|until|while|continue|break)\>"
|
||||
color green "(\{|\}|\(|\)|\;|\]|\[|`|\\|\$|<|>|!|=|&|\|)"
|
||||
color green "-(e|d|f|r|g|u|w|x|L)\>"
|
||||
color green "-(eq|ne|gt|lt|ge|le|s|n|z)\>"
|
||||
color statement "\b(case|do|done|elif|else|esac|exit|fi|for|function|if|in|local|read|return|select|shift|then|time|until|while|continue|break)\b"
|
||||
color statement "(\{|\}|\(|\)|\;|\]|\[|`|\\|\$|<|>|!|=|&|\|)"
|
||||
color statement "-(e|d|f|r|g|u|w|x|L)\b"
|
||||
color statement "-(eq|ne|gt|lt|ge|le|s|n|z)\b"
|
||||
## Highlight variables ... official portage ones in red, all others in bright red
|
||||
color brightred "\$\{?[a-zA-Z_0-9]+\}?"
|
||||
color red "\<(ARCH|HOMEPAGE|DESCRIPTION|IUSE|SRC_URI|LICENSE|SLOT|KEYWORDS|FILESDIR|WORKDIR|(P|R)?DEPEND|PROVIDE|DISTDIR|RESTRICT|USERLAND)\>"
|
||||
color red "\<(S|D|T|PV|PF|P|PN|A)\>" "\<C(XX)?FLAGS\>" "\<LDFLAGS\>" "\<C(HOST|TARGET|BUILD)\>"
|
||||
color preproc "\$\{?[a-zA-Z_0-9]+\}?"
|
||||
color special "\b(ARCH|HOMEPAGE|DESCRIPTION|IUSE|SRC_URI|LICENSE|SLOT|KEYWORDS|FILESDIR|WORKDIR|(P|R)?DEPEND|PROVIDE|DISTDIR|RESTRICT|USERLAND)\b"
|
||||
color special "\b(S|D|T|PV|PF|P|PN|A)\b" "\bC(XX)?FLAGS\b" "\bLDFLAGS\b" "\bC(HOST|TARGET|BUILD)\b"
|
||||
## Highlight portage commands
|
||||
color magenta "\<use(_(with|enable))?\> [!a-zA-Z0-9_+ -]*" "inherit.*"
|
||||
color brightblue "\<e(begin|end|conf|install|make|warn|infon?|error|log|patch|new(group|user))\>"
|
||||
color brightblue "\<die\>" "\<use(_(with|enable))?\>" "\<inherit\>" "\<has\>" "\<(has|best)_version\>" "\<unpack\>"
|
||||
color brightblue "\<(do|new)(ins|s?bin|doc|lib(\.so|\.a)|man|info|exe|initd|confd|envd|pam|menu|icon)\>"
|
||||
color brightblue "\<do(python|sed|dir|hard|sym|html|jar|mo)\>" "\<keepdir\>"
|
||||
color brightblue "prepall(docs|info|man|strip)" "prep(info|lib|lib\.(so|a)|man|strip)"
|
||||
color brightblue "\<(doc|ins|exe)into\>" "\<f(owners|perms)\>" "\<(exe|ins|dir)opts\>"
|
||||
color identifier "\buse(_(with|enable))?\b [!a-zA-Z0-9_+ -]*" "inherit.*"
|
||||
color statement "\be(begin|end|conf|install|make|warn|infon?|error|log|patch|new(group|user))\b"
|
||||
color statement "\bdie\b" "\buse(_(with|enable))?\b" "\binherit\b" "\bhas\b" "\b(has|best)_version\b" "\bunpack\b"
|
||||
color statement "\b(do|new)(ins|s?bin|doc|lib(\.so|\.a)|man|info|exe|initd|confd|envd|pam|menu|icon)\b"
|
||||
color statement "\bdo(python|sed|dir|hard|sym|html|jar|mo)\b" "\bkeepdir\b"
|
||||
color statement "prepall(docs|info|man|strip)" "prep(info|lib|lib\.(so|a)|man|strip)"
|
||||
color statement "\b(doc|ins|exe)into\b" "\bf(owners|perms)\b" "\b(exe|ins|dir)opts\b"
|
||||
## Highlight common commands used in ebuilds
|
||||
color blue "\<make\>" "\<(cat|cd|chmod|chown|cp|echo|env|export|grep|let|ln|mkdir|mv|rm|sed|set|tar|touch|unset)\>"
|
||||
color type "\bmake\b" "\b(cat|cd|chmod|chown|cp|echo|env|export|grep|let|ln|mkdir|mv|rm|sed|set|tar|touch|unset)\b"
|
||||
## Highlight comments (doesnt work that well)
|
||||
color yellow "#.*$"
|
||||
color comment "#.*$"
|
||||
## Highlight strings (doesnt work that well)
|
||||
color brightyellow ""(\\.|[^\"])*"" "'(\\.|[^'])*'"
|
||||
## Trailing space is bad!
|
||||
color ,green "[[:space:]]+$"
|
||||
color constant.string ""(\\.|[^\"])*"" "'(\\.|[^'])*'"
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
syntax "ini" "\.(ini|desktop|lfl|override)$" "(mimeapps\.list|pinforc|setup\.cfg)$" "weechat/.+\.conf$"
|
||||
header "^\[[A-Za-z]+\]$"
|
||||
|
||||
color brightcyan "\<(true|false)\>"
|
||||
color cyan "^[[:space:]]*[^=]*="
|
||||
color brightmagenta "^[[:space:]]*\[.*\]$"
|
||||
color red "[=;]"
|
||||
color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'"
|
||||
color brightblack "(^|[[:space:]])#([^{].*)?$"
|
||||
color ,green "[[:space:]]+$"
|
||||
color ,red " + +| + +"
|
||||
color constant "\b(true|false)\b"
|
||||
color identifier "^[[:space:]]*[^=]*="
|
||||
color special "^[[:space:]]*\[.*\]$"
|
||||
color statement "[=;]"
|
||||
color comment "(^|[[:space:]])#([^{].*)?$"
|
||||
color constant.string ""(\\.|[^"])*"|'(\\.|[^'])*'"
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
syntax "json" "\.json$"
|
||||
header "^\{$"
|
||||
|
||||
color blue "\<[-]?[1-9][0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>"
|
||||
color cyan "\<null\>"
|
||||
color brightcyan "\<(true|false)\>"
|
||||
color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'"
|
||||
color brightyellow "\"(\\"|[^"])*\"[[:space:]]*:" "'(\'|[^'])*'[[:space:]]*:"
|
||||
color magenta "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]"
|
||||
color constant.number "\b[-+]?([1-9][0-9]*|0[0-7]*|0x[0-9a-fA-F]+)([uU][lL]?|[lL][uU]?)?\b"
|
||||
color constant.number "\b[-+]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([EePp][+-]?[0-9]+)?[fFlL]?"
|
||||
color constant.number "\b[-+]?([0-9]+[EePp][+-]?[0-9]+)[fFlL]?"
|
||||
color constant "\b(null)\b"
|
||||
color constant "\b(true|false)\b"
|
||||
color constant.string ""(\\.|[^"])*"|'(\\.|[^'])*'"
|
||||
color statement "\"(\\"|[^"])*\"[[:space:]]*:" "'(\'|[^'])*'[[:space:]]*:"
|
||||
color constant "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]"
|
||||
color ,green "[[:space:]]+$"
|
||||
color ,red " + +| + +"
|
||||
|
||||
21
runtime/syntax/lfe.micro
Normal file
21
runtime/syntax/lfe.micro
Normal file
@@ -0,0 +1,21 @@
|
||||
syntax "lfe" "lfe$" "\.lfe$"
|
||||
|
||||
# Parens are everywhere!
|
||||
color statement "\("
|
||||
color statement "\)"
|
||||
|
||||
# Good overrides for LFE in particular
|
||||
color type "defun|define-syntax|define|defmacro|defmodule|export"
|
||||
|
||||
# Dirty base cases stolen from the generic lisp syntax
|
||||
color constant "\ [A-Za-z][A-Za-z0-9_-]+\ "
|
||||
color statement "\(([-+*/<>]|<=|>=)|'"
|
||||
color constant.number "\<[0-9]+\>"
|
||||
color constant.string "\"(\\.|[^"])*\""
|
||||
color special "['|`][A-Za-z][A-Za-z0-9_-]+"
|
||||
color constant.string "\\.?"
|
||||
color comment "(^|[[:space:]]);.*"
|
||||
|
||||
# Some warning colors because our indents are wrong.
|
||||
color ,green "[[:space:]]+$"
|
||||
color ,red " + +| + +"
|
||||
10
runtime/syntax/micro.micro
Normal file
10
runtime/syntax/micro.micro
Normal file
@@ -0,0 +1,10 @@
|
||||
# Micro syntax by <nickolay02@inbox.ru>
|
||||
syntax "micro" "\.(micro)$"
|
||||
|
||||
color statement "\b(syntax|color|color-link)\b"
|
||||
color statement "\b(start=|end=)\b"
|
||||
color identifier "\b(default|comment|identifier|constant|constant|string|constant|number|statement|preproc|type|special|underlined|error|todo|statusline|indent-char|line=number|gutter-error|gutter-warning|cursor-line)\b"
|
||||
color constant.number "\b(|h|A|0x)+[0-9]+(|h|A)+\b"
|
||||
color constant.number "\b0x[0-9 a-f A-F]+\b"
|
||||
color constant.string ""(\\.|[^"])*""
|
||||
color comment "#.*"
|
||||
24
runtime/syntax/pascal.micro
Normal file
24
runtime/syntax/pascal.micro
Normal file
@@ -0,0 +1,24 @@
|
||||
syntax "pascal" "\.pas$"
|
||||
|
||||
# color identifier "\b[\pL_][\pL_\pN]*\b"
|
||||
|
||||
color comment "//.*"
|
||||
color comment start="\(\*" end="\*\)"
|
||||
color comment start="({)(?:[^$])" end="}"
|
||||
|
||||
color special start="asm" end="end"
|
||||
|
||||
color type "\b(?i:(string|ansistring|widestring|shortstring|char|ansichar|widechar|boolean|byte|shortint|word|smallint|longword|cardinal|longint|integer|int64|single|currency|double|extended))\b"
|
||||
|
||||
color statement "\b(?i:(and|asm|array|begin|break|case|const|constructor|continue|destructor|div|do|downto|else|end|file|for|function|goto|if|implementation|in|inline|interface|label|mod|not|object|of|on|operator|or|packed|procedure|program|record|repeat|resourcestring|set|shl|shr|then|to|type|unit|until|uses|var|while|with|xor))\b"
|
||||
color statement "\b(?i:(as|class|dispose|except|exit|exports|finalization|finally|inherited|initialization|is|library|new|on|out|property|raise|self|threadvar|try))\b"
|
||||
color statement "\b(?i:(absolute|abstract|alias|assembler|cdecl|cppdecl|default|export|external|forward|generic|index|local|name|nostackframe|oldfpccall|override|pascal|private|protected|public|published|read|register|reintroduce|safecall|softfloat|specialize|stdcall|virtual|write))\b"
|
||||
|
||||
color constant "\b(?i:(false|true|nil))\b"
|
||||
color constant "\$[0-9A-Fa-f]+" "\b[+-]?[0-9]+([.]?[0-9]+)?(?i:e[+-]?[0-9]+)?"
|
||||
|
||||
color constant.string "'(?:[^']+|'')*'"
|
||||
|
||||
|
||||
|
||||
color preproc start="{\$" end="}"
|
||||
@@ -1,40 +1,30 @@
|
||||
## PHP Syntax Highlighting
|
||||
syntax "php" "\.php[2345s~]?$"
|
||||
color white start="<\?(php|=)?" end="\?>"
|
||||
# Functions
|
||||
color brightblue "([a-zA-Z0-9_-]*)\("
|
||||
# Constructs
|
||||
color brightblue "(class|extends|goto) ([a-zA-Z0-9_]*)"
|
||||
color green "[^a-z0-9_-]{1}(var|class|function|echo|case|break|default|exit|switch|if|else|elseif|endif|foreach|endforeach|@|while|public|private|protected|return|true|false|null|TRUE|FALSE|NULL|const|static|extends|as|array|require|include|require_once|include_once|define|do|continue|declare|goto|print|in|namespace|use)[^a-z0-9_-]{1}"
|
||||
color brightblue "[a-zA-Z0-9]+:"
|
||||
# Variables
|
||||
color white "\$[a-zA-Z_0-9$]*|[=!<>]"
|
||||
color white "\->[a-zA-Z_0-9$]*|[=!<>]"
|
||||
# Special Characters
|
||||
color yellow "[.,{}();]"
|
||||
color yellow "\["
|
||||
color yellow "\]"
|
||||
color yellow "[=][^>]"
|
||||
# Numbers
|
||||
color magenta "[+-]*([0-9]\.)*[0-9]+([eE][+-]?([0-9]\.)*[0-9])*"
|
||||
color magenta "0x[0-9a-zA-Z]*"
|
||||
# Special Variables
|
||||
color brightblue "(\$this|parent::|self::|\$this->)"
|
||||
# Bitwise Operations
|
||||
color magenta "(\;|\||\^){1}"
|
||||
# And/Or/SRO/etc
|
||||
color green "(\;\;|\|\||::|=>|->)"
|
||||
# Online Comments
|
||||
color brightyellow "(#.*|//.*)$"
|
||||
# STRINGS!
|
||||
color red "('[^']*')|(\"[^\"]*\")"
|
||||
# Inline Variables
|
||||
color white "\{\$[^}]*\}"
|
||||
# PHP Tags
|
||||
color red "(<\?(php)?|\?>)"
|
||||
# General HTML
|
||||
color red start="\?>" end="<\?(php|=)?"
|
||||
# trailing whitespace
|
||||
color ,green "[^[:space:]]{1}[[:space:]]+$"
|
||||
# multi-line comments
|
||||
color brightyellow start="/\*" end="\*/"
|
||||
color default start="<\?(php|=)?" end="\?>"
|
||||
|
||||
color special "([a-zA-Z0-9_-]+)\("
|
||||
|
||||
color identifier "(var|class|goto|extends|function|echo|case|break|default|exit|switch|foreach|endforeach|while|const|static|extends|as|require|include|require_once|include_once|define|do|continue|declare|goto|print|in|trait|interface|[E|e]xception|array|int|string|bool|iterable|void)[\s|\)]"
|
||||
|
||||
color identifier "[a-zA-Z\\]+::"
|
||||
|
||||
color identifier "new\s([a-zA-Z0-9\\]+)"
|
||||
color identifier "([A-Z][a-zA-Z0-9_]+)\s"
|
||||
color identifier "([A-Z0-9_]+)[;|\s|\)|,]"
|
||||
|
||||
color statement "(implements|abstract|global|public|instanceof|private|protected|static|if|else|elseif|endif|namespace|use|as|new|throw|catch|try|return)[\s|;]"
|
||||
|
||||
color constant "(true|false|null|TRUE|FALSE|NULL)"
|
||||
|
||||
color constant "[\s|=|>|\s|\(|/|+|-|\*|\[](\d+)"
|
||||
|
||||
color identifier "(\$this|parent|self|\$this->)"
|
||||
|
||||
color statement "(=>|===|!==|==|!=|&&|\|\||::|=|->|\!)"
|
||||
|
||||
color default "(\$[a-zA-Z0-9\-_]+)"
|
||||
color default "[\(|\)|/|+|-|\*|\[|,|;]"
|
||||
|
||||
color constant.string "('.*?'|\".*?\")"
|
||||
|
||||
color comment start="/\*" end="\*/"
|
||||
color comment "(#.*|//.*)$"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
syntax "shell" "\.sh$" "\.bash" "\.bashrc" "bashrc" "\.bash_aliases" "bash_aliases" "\.bash_functions" "bash_functions" "\.bash_profile" "bash_profile" "Pkgfile" "PKGBUILD" ".ebuild\$" "APKBUILD"
|
||||
syntax "shell" "\.sh$" "\.bash" "\.bashrc" "bashrc" "\.bash_aliases" "bash_aliases" "\.bash_functions" "bash_functions" "\.bash_profile" "bash_profile" "Pkgfile" "pkgmk.conf" "profile" "rc.conf" "PKGBUILD" ".ebuild\$" "APKBUILD"
|
||||
header "^#!.*/(env +)?(ba)?sh( |$)"
|
||||
|
||||
# Numbers
|
||||
|
||||
20
runtime/syntax/typescript.micro
Normal file
20
runtime/syntax/typescript.micro
Normal file
@@ -0,0 +1,20 @@
|
||||
syntax "typescript" "\.ts$"
|
||||
|
||||
color constant.number "\b[-+]?([1-9][0-9]*|0[0-7]*|0x[0-9a-fA-F]+)([uU][lL]?|[lL][uU]?)?\b"
|
||||
color constant.number "\b[-+]?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([EePp][+-]?[0-9]+)?[fFlL]?"
|
||||
color constant.number "\b[-+]?([0-9]+[EePp][+-]?[0-9]+)[fFlL]?"
|
||||
color identifier "[A-Za-z_][A-Za-z0-9_]*[[:space:]]*[(]"
|
||||
color statement "\b(break|case|catch|continue|default|delete|do|else|finally)\b"
|
||||
color statement "\b(declare|interface|import|export|from|for|function|get|if|in|instanceof|new|return|set|switch)\b"
|
||||
color statement "\b(switch|this|throw|try|typeof|var|void|while|with|async|await)\b"
|
||||
color constant "\b(null|undefined|NaN)\b"
|
||||
color constant "\b(true|false)\b"
|
||||
color type "\b(Array|Boolean|Date|Enumerator|Error|Function|Math|string|number|boolean|any)\b"
|
||||
color type "\b(Number|Object|RegExp|String)\b"
|
||||
color statement "[-+/*=<>!~%?:&|]"
|
||||
color constant "/[^*]([^/]|(\\/))*[^\\]/[gim]*"
|
||||
color constant "\\[0-7][0-7]?[0-7]?|\\x[0-9a-fA-F]+|\\[bfnrt'"\?\\]"
|
||||
color comment "(^|[[:space:]])//.*"
|
||||
color comment "/\*.+\*/"
|
||||
color todo "TODO:?"
|
||||
color constant.string ""(\\.|[^"])*"|'(\\.|[^'])*'"
|
||||
@@ -1,13 +1,11 @@
|
||||
syntax "yaml" "\.ya?ml$"
|
||||
header "^---" "%YAML"
|
||||
|
||||
color green "(^| )!!(binary|bool|float|int|map|null|omap|seq|set|str) "
|
||||
color brightcyan "\<(YES|yes|Y|y|ON|on|NO|no|N|n|OFF|off)\>"
|
||||
color brightcyan "\<(true|false)\>"
|
||||
color red ":[[:space:]]" "\[" "\]" ":[[:space:]]+[|>]" "^[[:space:]]*- "
|
||||
color brightyellow "[[:space:]][\*&][A-Za-z0-9]+"
|
||||
color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'"
|
||||
color brightblack "(^|[[:space:]])#([^{].*)?$"
|
||||
color brightmagenta "^---" "^\.\.\." "^%YAML" "^%TAG"
|
||||
color ,green "[[:space:]]+$"
|
||||
color ,red " + +| + +"
|
||||
color type "(^| )!!(binary|bool|float|int|map|null|omap|seq|set|str) "
|
||||
color constant "\b(YES|yes|Y|y|ON|on|NO|no|N|n|OFF|off)\b"
|
||||
color constant "\b(true|false)\b"
|
||||
color statement ":[[:space:]]" "\[" "\]" ":[[:space:]]+[|>]" "^[[:space:]]*- "
|
||||
color identifier "[[:space:]][\*&][A-Za-z0-9]+"
|
||||
color constant.string ""(\\.|[^"])*"|'(\\.|[^'])*'"
|
||||
color comment "(^|[[:space:]])#([^{].*)?$"
|
||||
color special "^---" "^\.\.\." "^%YAML" "^%TAG"
|
||||
|
||||
10
tools/build-date.go
Normal file
10
tools/build-date.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(time.Now().Local().Format("January 02, 2006"))
|
||||
}
|
||||
117
tools/pre-release.sh
Executable file
117
tools/pre-release.sh
Executable file
@@ -0,0 +1,117 @@
|
||||
# This script creates releases on Github for micro
|
||||
# It assumes that the binaries are in the current directory
|
||||
# You must have the correct Github access token to run this script
|
||||
|
||||
# $1 is the title, $2 is the description
|
||||
|
||||
commitID=$(git rev-parse HEAD)
|
||||
tag="v$1"
|
||||
|
||||
echo "Creating tag"
|
||||
git tag $tag $commitID
|
||||
git push --tags
|
||||
|
||||
echo "Creating new release"
|
||||
github-release release \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "$1" \
|
||||
--description "$2" \
|
||||
--pre-release
|
||||
|
||||
echo "Uploading OSX binary"
|
||||
github-release upload \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "micro-$1-osx.tar.gz" \
|
||||
--file binaries/micro-$1-osx.tar.gz
|
||||
|
||||
echo "Uploading Linux 64 binary"
|
||||
github-release upload \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "micro-$1-linux64.tar.gz" \
|
||||
--file binaries/micro-$1-linux64.tar.gz
|
||||
|
||||
echo "Uploading Linux 32 binary"
|
||||
github-release upload \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "micro-$1-linux32.tar.gz" \
|
||||
--file binaries/micro-$1-linux32.tar.gz
|
||||
|
||||
echo "Uploading Linux Arm binary"
|
||||
github-release upload \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "micro-$1-linux-arm.tar.gz" \
|
||||
--file binaries/micro-$1-linux-arm.tar.gz
|
||||
|
||||
echo "Uploading FreeBSD 64 binary"
|
||||
github-release upload \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "micro-$1-freebsd64.tar.gz" \
|
||||
--file binaries/micro-$1-freebsd64.tar.gz
|
||||
|
||||
echo "Uploading FreeBSD 32 binary"
|
||||
github-release upload \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "micro-$1-freebsd32.tar.gz" \
|
||||
--file binaries/micro-$1-freebsd32.tar.gz
|
||||
|
||||
echo "Uploading OpenBSD 64 binary"
|
||||
github-release upload \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "micro-$1-openbsd64.tar.gz" \
|
||||
--file binaries/micro-$1-openbsd64.tar.gz
|
||||
|
||||
echo "Uploading OpenBSD 32 binary"
|
||||
github-release upload \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "micro-$1-openbsd32.tar.gz" \
|
||||
--file binaries/micro-$1-openbsd32.tar.gz
|
||||
|
||||
echo "Uploading NetBSD 64 binary"
|
||||
github-release upload \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "micro-$1-netbsd64.tar.gz" \
|
||||
--file binaries/micro-$1-netbsd64.tar.gz
|
||||
|
||||
echo "Uploading NetBSD 32 binary"
|
||||
github-release upload \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "micro-$1-netbsd32.tar.gz" \
|
||||
--file binaries/micro-$1-netbsd32.tar.gz
|
||||
|
||||
echo "Uploading Windows 64 binary"
|
||||
github-release upload \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "micro-$1-win64.zip" \
|
||||
--file binaries/micro-$1-win64.zip
|
||||
|
||||
echo "Uploading Windows 32 binary"
|
||||
github-release upload \
|
||||
--user zyedidia \
|
||||
--repo micro \
|
||||
--tag $tag \
|
||||
--name "micro-$1-win32.zip" \
|
||||
--file binaries/micro-$1-win32.zip
|
||||
@@ -18,7 +18,6 @@ github-release release \
|
||||
--tag $tag \
|
||||
--name "$1" \
|
||||
--description "$2" \
|
||||
--pre-release
|
||||
|
||||
echo "Uploading OSX binary"
|
||||
github-release upload \
|
||||
@@ -115,3 +114,4 @@ github-release upload \
|
||||
--tag $tag \
|
||||
--name "micro-$1-win32.zip" \
|
||||
--file binaries/micro-$1-win32.zip
|
||||
|
||||
|
||||
Reference in New Issue
Block a user