Compare commits

...

52 Commits

Author SHA1 Message Date
Zachary Yedidia
319a5cba74 Switch to vfsgen for runtime generation 2020-06-16 15:15:50 -04:00
Hugo Locurcio
5bfc892a74 Add support for dozens more languages to the comment plugin (#1729) 2020-06-16 00:49:07 -04:00
Ryan Westlund
1793b6268b Add comment support for Haskell (#1728) 2020-06-15 16:11:51 -04:00
Zachary Yedidia
9b62aa4170 Merge branch 'p-e-w-faster-runewidth' 2020-06-13 17:00:03 -04:00
Zachary Yedidia
6fef5d6232 Merge branch 'faster-runewidth' of https://github.com/p-e-w/micro into p-e-w-faster-runewidth 2020-06-13 16:59:52 -04:00
Zachary Yedidia
fe19b13b3b Update go-shellquote for windows 2020-06-13 16:58:20 -04:00
Philipp Emanuel Weidmann
6559b116c0 Make determining rune width faster 2020-06-13 08:59:17 +05:30
Zachary Yedidia
ca976a8a3c Update runtime build script
Ref #1687
2020-06-12 20:54:37 -04:00
Zachary Yedidia
cfc595e80e Fix MoveLines on last line of buffer
Fixes #1723
Fixes #1724
2020-06-12 15:16:27 -04:00
Zachary Yedidia
fde4b92b9f More consistent key labels in docs 2020-06-12 14:41:57 -04:00
Zachary Yedidia
b8ec7b320a Add note for macOS terminals in docs 2020-06-12 14:20:26 -04:00
Zachary Yedidia
1786165d8b Merge branch 'master' of https://github.com/zyedidia/micro 2020-06-12 14:16:53 -04:00
Zachary Yedidia
0322e91933 Update readme 2020-06-12 14:16:47 -04:00
Ján Priner
b2261fc225 Add latex support in comment plugin (#1725) 2020-06-12 12:58:51 -04:00
Philipp Emanuel Weidmann
5ce26cca71 Make determining whether a code point represents a combining mark faster (#1719) 2020-06-12 00:10:00 -04:00
Zachary Yedidia
efb38b8636 Merge branch 'settings-config'
With these changes, settings.json should only contain options that
have been modified from their default values. Micro will actively
options that are set to default values from the settings.json file.
To see a full list of settings and their defaults, see the "options"
documentation, as well as `micro -options`.
2020-06-09 16:34:37 -04:00
Zachary Yedidia
0654db334a Show key name in raw pane 2020-06-09 15:57:52 -04:00
Zachary Yedidia
660d345880 Don't apply cli options to settings.json 2020-06-08 22:19:15 -04:00
Dmitry Maluka
1f58eecf3c Lower priority of cursorline and colorcolumn highlighting (#1697)
Fixes #1665
2020-06-08 16:15:54 -04:00
Zachary Yedidia
ae05ff1811 settings.json only contains modified settings
If a setting has a default value it will not be listed in settings.json.
2020-06-08 15:33:38 -04:00
Zachary Yedidia
43924646f6 Merge 2020-06-08 13:55:24 -04:00
Zachary Yedidia
79ee757757 Only start autocompletion for alphanumerics
Ref #1712
2020-06-08 13:54:31 -04:00
Ryan Westlund
006165230d python.yaml: add async as a keyword (#1713)
await is already a keyword, but async is not.
2020-06-08 13:45:05 -04:00
Zachary Yedidia
ead07e0b60 Expose ConfigDir and Tabs to plugins
Access with `micro.ConfigDir` (constant value) and `micro.Tabs()`.
2020-06-07 18:21:46 -04:00
Zachary Yedidia
140662f1ec Verify that all settings have correct type
This prevents crashes that occur when the user has put the wrong
type for a setting manually in the settings.json file.
2020-06-07 17:31:16 -04:00
Zachary Yedidia
44c1929f9d Fix mouse support in command bar 2020-06-07 15:46:12 -04:00
Zachary Yedidia
397fe634d7 Update tcell to fix escape sequence bug 2020-06-07 15:22:17 -04:00
Zachary Yedidia
2e3d08580e Merge 2020-06-06 15:56:36 -04:00
Zachary Yedidia
466889f540 Fix fileformat for newly created files
Fixes #1575
2020-06-06 15:56:13 -04:00
Dmitry Maluka
63900cb395 Fix highlighting at the end of line (#1705)
Fixes #1664
2020-06-04 23:32:31 -04:00
Chloe Kudryavtsev
07860b8973 Add mksh to the set of supported shells (#1703) 2020-06-03 13:30:42 -04:00
Zachary Yedidia
b473fe458d Merge 2020-06-03 00:27:51 -04:00
Zachary Yedidia
8cf56bfc56 Up arrow on first line brings to start
Fixes #1701
2020-06-03 00:27:24 -04:00
Sijmen J. Mulder
51050811eb Add pkgsrc instruction to readme (#1699) 2020-06-02 16:49:18 -04:00
Zachary Yedidia
14cd3cdbf8 Update readme 2020-06-01 00:17:52 -04:00
Zachary Yedidia
51ab8f9914 Unicode replacement char for non-displayable chars 2020-05-30 18:11:52 -04:00
Zachary Yedidia
afeb07a024 More fixes for parsecursor
Fixes #1695
Fixes #1696
2020-05-30 12:23:29 -04:00
Zachary Yedidia
3fc9a8ad9e Fix handling of +LINE:COL syntax
Fixes #1685
2020-05-29 22:48:23 -04:00
Zachary Yedidia
b05d3a5193 Slightly improve performance for very long lines 2020-05-29 15:31:13 -04:00
Zachary Yedidia
ffc922a7c5 Only perform save callback if save was successful
Fixes #1684
2020-05-29 15:02:38 -04:00
Zachary Yedidia
eeab114ed5 Add parsecursor option for file:line:col syntax
This option is disabled by default, and when enabled causes micro
to parse `:line:col` as a location for the cursor rather than
as part of the filename.

Closes #1650
Closes #1685
2020-05-29 14:55:24 -04:00
Zachary Yedidia
8bd7e5807c Always use current pane for keybinding actions
Fixes #1677
2020-05-29 14:38:29 -04:00
Andrew Clarke
9b59e07b47 Use "goto -1" to move cursor to end of document. (#1691) 2020-05-29 13:29:09 -04:00
Colin Hughes
00edf0207f Added hybrid line numbers (#1690)
* Added hybrid line numbers

* Changed rulerhybrid to relativeruler, modified documentation accordingly.

* Reverted go.mod and go.sum
I don't know how they got changed but they are good now.

Co-authored-by: Colin Hughes <semilin@pop-os.localdomain>
2020-05-28 22:24:09 -04:00
Zachary Yedidia
a95b17a4e7 Update readme 2020-05-28 18:39:17 -04:00
Zachary Yedidia
8956448fca UpdateRules after save is successful 2020-05-28 13:06:29 -04:00
Zachary Yedidia
a915cf9283 Fix '> save' command 2020-05-28 13:02:09 -04:00
Zachary Yedidia
dd10869eca Update readme 2020-05-28 11:59:31 -04:00
Peder B. Sundt
4356c7e434 Tweak railscast colorscheme to better reflect original (#1297) 2020-05-28 11:50:35 -04:00
axxx007xxxz
2e770ce9ce README: Add Fedora install instructions (#1671) 2020-05-28 11:49:18 -04:00
pyfisch
381e1b639d Rewrite TOML syntax file (#1681) 2020-05-26 14:10:27 -04:00
Shinichi TAMURA
cc09712d14 set bash-fc file's syntax as shell (#1679)
* set bash-fc file's syntax as shell

* remove dups from shell file matcher
2020-05-24 23:50:30 -04:00
40 changed files with 942 additions and 7809 deletions

1
.gitignore vendored
View File

@@ -18,3 +18,4 @@ tools/info-plist
tools/bindata
tools/vscode-tests/
*.hdr
assets_vfsdata.go

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "tools/go-bindata"]
path = tools/go-bindata
url = https://github.com/zyedidia/go-bindata

View File

@@ -45,12 +45,7 @@ fetch-tags:
# Builds the runtime
runtime:
git submodule update --init
go run runtime/syntax/make_headers.go runtime/syntax
go build -o tools/bindata ./tools/go-bindata
tools/bindata -pkg config -nomemcopy -nometadata -o runtime.go runtime/...
mv runtime.go internal/config
gofmt -w internal/config/runtime.go
go generate ./internal/config
testgen:
mkdir -p tools/vscode-tests
@@ -79,7 +74,7 @@ bench-compare:
for i in 1 2 3; do \
go test -bench=. ./internal/...; \
done > benchmark_results
benchstat benchmark_results_baseline benchmark_results
benchstat -alpha 0.15 benchmark_results_baseline benchmark_results
clean:
rm -f micro

View File

@@ -44,7 +44,7 @@ You can also check out the website for Micro at https://micro-editor.github.io.
- Easy to use and install.
- No dependencies or external files are needed — just the binary you can download further down the page.
- Multiple cursors.
- Common keybindings (<kbd>Ctrl+S</kbd>, <kbd>Ctrl+C</kbd>, <kbd>Ctrl+V</kbd>, <kbd>Ctrl+Z</kbd>, …).
- Common keybindings (<kbd>Ctrl-s</kbd>, <kbd>Ctrl-c</kbd>, <kbd>Ctrl-v</kbd>, <kbd>Ctrl-z</kbd>, …).
- 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).
@@ -53,13 +53,13 @@ You can also check out the website for Micro at https://micro-editor.github.io.
- 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 Mingw/Cygwin is not (see below)
- Note that while Windows is supported Mingw/Cygwin is not (see below).
- Plugin system (plugins are written in Lua).
- micro has a built-in plugin manager to automatically install, remove, and update plugins.
- Built-in diff gutter
- Simple autocompletion
- Built-in diff gutter.
- Simple autocompletion.
- Persistent undo.
- Automatic linting and error notifications
- Automatic linting and error notifications.
- Syntax highlighting for over [130 languages](runtime/syntax).
- Color scheme support.
- By default, micro comes with 16, 256, and true color themes.
@@ -76,17 +76,15 @@ To install micro, you can download a [prebuilt binary](https://github.com/zyedid
If you want more information about ways to install micro, see this [wiki page](https://github.com/zyedidia/micro/wiki/Installing-Micro).
Use `micro -version` to get the version information after installing. It is only guaranteed that you are installing the most recent
stable version if you install from the prebuilt binaries, Homebrew, or Snap.
### Prebuilt binaries
All you need to install micro is one file, the binary itself. It's as simple as that!
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.
Running `micro -version` will give you the version information.
### Installation script
There is a script which can install micro for you by downloading the latest prebuilt binary. You can find it at <https://getmic.ro>.
@@ -97,7 +95,7 @@ You can easily install micro by running
curl https://getmic.ro | bash
```
The script will install the micro binary to the current directory. See its [GitHub repository](https://github.com/benweissmann/getmic.ro) for more information.
The script will place the micro binary in the current directory. See its [GitHub repository](https://github.com/benweissmann/getmic.ro) for more information.
### Package managers
@@ -117,27 +115,25 @@ On Linux, you can install micro through [snap](https://snapcraft.io/docs/core/in
snap install micro --classic
```
On Debian `unstable | testing | buster-backports` and Ubuntu `focal` (20.04), micro is available
via `apt`:
```
sudo apt install micro
```
**Note for Linux:** for interfacing with the local system clipboard, `xclip` or `xsel`
must be installed. Please see the section on [Linux clipboard support](https://github.com/zyedidia/micro#linux-clipboard-support)
further below.
Micro is also available through other package managers on Linux such as AUR, Nix, and package managers
for other operating systems:
Micro is also available through other package managers on Linux such as apt, dnf, AUR, Nix, and package managers
for other operating systems. These packages are not guaranteed to be up-to-date.
* Windows: [Chocolatey](https://chocolatey.org) and [Scoop](https://github.com/lukesampson/scoop)
* `choco install micro`
* `scoop install micro`
* OpenBSD: Available in the ports tree and also available as a binary package
* `pkd_add -v micro`
* Arch Linux, CRUX, Termux for Android
* See details in the [wiki page](https://github.com/zyedidia/micro/wiki/Installing-Micro)
* Linux: Available in distro-specific package managers.
* `apt install micro` (Ubuntu 20.04 `focal`, and Debian `unstable | testing | buster-backports`).
* `dnf install micro` (Fedora).
* `yay -S micro` (Arch Linux).
* See [wiki](https://github.com/zyedidia/micro/wiki/Installing-Micro) for details about CRUX, Termux.
* Windows: [Chocolatey](https://chocolatey.org) and [Scoop](https://github.com/lukesampson/scoop).
* `choco install micro`.
* `scoop install micro`.
* OpenBSD: Available in the ports tree and also available as a binary package.
* `pkd_add -v micro`.
* NetBSD, macOS, Linux, Illumos, etc. with [pkgsrc](http://www.pkgsrc.org/)-current:
* `pkg_add micro`
### Building from source
@@ -173,7 +169,7 @@ CGO_ENABLED=0 make build
### macOS terminal
If you are using macOS, you should consider using [iTerm2](http://iterm2.com/) instead of the default terminal (Terminal.app). The iTerm2 terminal has much better mouse support as well as better handling of key events. For best keybinding behavior, choose `xterm defaults` under `Preferences->Profiles->Keys->Load Preset`. The newest versions also support true color.
If you are using macOS, you should consider using [iTerm2](http://iterm2.com/) instead of the default terminal (Terminal.app). The iTerm2 terminal has much better mouse support as well as better handling of key events. For best keybinding behavior, choose `xterm defaults` under `Preferences->Profiles->Keys->Presets...`, and select `Esc+` for `Left Option Key` in the same menu. The newest versions also support true color.
If you still insist on using the default Mac terminal, be sure to set `Use Option key as Meta key` under
`Preferences->Profiles->Keyboard` to use <kbd>option</kbd> as <kbd>alt</kbd>.
@@ -191,7 +187,7 @@ If you don't have these commands, micro will use an internal clipboard for copy
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 mode. Try changing the color scheme to `simple`
by pressing <kbd>Ctrl+E</kbd> in micro and typing `set colorscheme simple`.
by pressing <kbd>Ctrl-e</kbd> in micro and typing `set colorscheme simple`.
If you are using the default Ubuntu terminal, to enable 256 make sure your `TERM` variable is set
to `xterm-256color`.
@@ -232,7 +228,7 @@ click to enable line selection.
## Documentation and Help
micro has a built-in help system which you can access by pressing <kbd>Ctrl+E</kbd> and typing `help`. Additionally, you can
micro has a built-in help system which you can access by pressing <kbd>Ctrl-e</kbd> and typing `help`. Additionally, you can
view the help files here:
- [main help](https://github.com/zyedidia/micro/tree/master/runtime/help/help.md)
@@ -253,3 +249,5 @@ You can use the [GitHub issue tracker](https://github.com/zyedidia/micro/issues)
to report bugs, ask questions, or suggest new features.
For a more informal setting to discuss the editor, you can join the [Gitter chat](https://gitter.im/zyedidia/micro).
Sometimes I am unresponsive, and I apologize! If that happens, please ping me.

View File

@@ -53,6 +53,9 @@ func luaImportMicro() *lua.LTable {
ulua.L.SetField(pkg, "CurTab", luar.New(ulua.L, func() *action.Tab {
return action.MainTab()
}))
ulua.L.SetField(pkg, "Tabs", luar.New(ulua.L, func() *action.TabList {
return action.Tabs
}))
return pkg
}
@@ -83,6 +86,7 @@ func luaImportMicroConfig() *lua.LTable {
ulua.L.SetField(pkg, "GetGlobalOption", luar.New(ulua.L, config.GetGlobalOption))
ulua.L.SetField(pkg, "SetGlobalOption", luar.New(ulua.L, action.SetGlobalOption))
ulua.L.SetField(pkg, "SetGlobalOptionNative", luar.New(ulua.L, action.SetGlobalOptionNative))
ulua.L.SetField(pkg, "ConfigDir", luar.New(ulua.L, config.ConfigDir))
return pkg
}

View File

@@ -8,6 +8,7 @@ import (
"regexp"
"runtime"
"sort"
"strconv"
"time"
"github.com/go-errors/errors"
@@ -44,7 +45,7 @@ func InitFlags() {
fmt.Println(" \tCleans the configuration directory")
fmt.Println("-config-dir dir")
fmt.Println(" \tSpecify a custom location for the configuration directory")
fmt.Println("[FILE]:LINE:COL")
fmt.Println("[FILE]:LINE:COL (if the `parsecursor` option is enabled)")
fmt.Println("+LINE:COL")
fmt.Println(" \tSpecify a line and column to start the cursor at when opening a buffer")
fmt.Println("-options")
@@ -155,18 +156,31 @@ func LoadInput() []*buffer.Buffer {
}
files := make([]string, 0, len(args))
flagStartPos := ""
flagr := regexp.MustCompile(`^\+\d+(:\d+)?$`)
flagStartPos := buffer.Loc{-1, -1}
flagr := regexp.MustCompile(`^\+(\d+)(?::(\d+))?$`)
for _, a := range args {
if flagr.MatchString(a) {
flagStartPos = a[1:]
} else {
if flagStartPos != "" {
files = append(files, a+":"+flagStartPos)
flagStartPos = ""
} else {
files = append(files, a)
match := flagr.FindStringSubmatch(a)
if len(match) == 3 && match[2] != "" {
line, err := strconv.Atoi(match[1])
if err != nil {
screen.TermMessage(err)
continue
}
col, err := strconv.Atoi(match[2])
if err != nil {
screen.TermMessage(err)
continue
}
flagStartPos = buffer.Loc{col - 1, line - 1}
} else if len(match) == 3 && match[2] == "" {
line, err := strconv.Atoi(match[1])
if err != nil {
screen.TermMessage(err)
continue
}
flagStartPos = buffer.Loc{0, line - 1}
} else {
files = append(files, a)
}
}
@@ -174,7 +188,7 @@ func LoadInput() []*buffer.Buffer {
// Option 1
// We go through each file and load it
for i := 0; i < len(files); i++ {
buf, err := buffer.NewBufferFromFile(files[i], btype)
buf, err := buffer.NewBufferFromFileAtLoc(files[i], btype, flagStartPos)
if err != nil {
screen.TermMessage(err)
continue
@@ -191,10 +205,10 @@ func LoadInput() []*buffer.Buffer {
screen.TermMessage("Error reading from stdin: ", err)
input = []byte{}
}
buffers = append(buffers, buffer.NewBufferFromString(string(input), filename, btype))
buffers = append(buffers, buffer.NewBufferFromStringAtLoc(string(input), filename, btype, flagStartPos))
} else {
// Option 3, just open an empty buffer
buffers = append(buffers, buffer.NewBufferFromString(string(input), filename, btype))
buffers = append(buffers, buffer.NewBufferFromStringAtLoc(string(input), filename, btype, flagStartPos))
}
return buffers
@@ -229,7 +243,10 @@ func main() {
if err != nil {
screen.TermMessage(err)
}
config.InitGlobalSettings()
err = config.InitGlobalSettings()
if err != nil {
screen.TermMessage(err)
}
// flag options
for k, v := range optionFlags {

9
go.mod
View File

@@ -10,6 +10,8 @@ require (
github.com/mitchellh/go-homedir v1.1.0
github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff
github.com/sergi/go-diff v1.1.0
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd // indirect
github.com/stretchr/testify v1.4.0
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb
github.com/zyedidia/clipboard v0.0.0-20200421031010-7c45b8673834
@@ -17,12 +19,17 @@ require (
github.com/zyedidia/highlight v0.0.0-20170330143449-201131ce5cf5
github.com/zyedidia/json5 v0.0.0-20200102012142-2da050b1a98d
github.com/zyedidia/pty v2.0.0+incompatible // indirect
github.com/zyedidia/tcell v1.4.5
github.com/zyedidia/tcell v1.4.6
github.com/zyedidia/terminal v0.0.0-20180726154117-533c623e2415
golang.org/x/text v0.3.2
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v2 v2.2.7
layeh.com/gopher-luar v1.0.7
)
replace github.com/kballard/go-shellquote => github.com/zyedidia/go-shellquote v0.0.0-20200613203517-eccd813c0655
replace github.com/mattn/go-runewidth => github.com/p-e-w/go-runewidth v0.0.10-0.20200613030200-3e1705c5c059
go 1.11

21
go.sum
View File

@@ -12,8 +12,6 @@ github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdk
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -23,16 +21,20 @@ github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tW
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/p-e-w/go-runewidth v0.0.10-0.20200613030200-3e1705c5c059 h1:/+h2b6i15wh4EWsFkfdNdBE1jjGA872tpXEyhPM5aYg=
github.com/p-e-w/go-runewidth v0.0.10-0.20200613030200-3e1705c5c059/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff h1:+6NUiITWwE5q1KO6SAfUX918c+Tab0+tGAM/mtdlUyA=
github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd h1:ug7PpSOB5RBPK1Kg6qskGBoP3Vnj/aNYFTznWvlkGo0=
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
@@ -40,12 +42,12 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/yuin/gopher-lua v0.0.0-20190206043414-8bfc7677f583/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb h1:ZkM6LRnq40pR1Ox0hTHlnpkcOTuFIDQpZ1IN8rKKhX0=
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
github.com/zyedidia/clipboard v0.0.0-20190823154308-241f98e9b197 h1:gYTNnAW6azuB3BbA6QYWO/H4F2ABSOjjw3Z03tlXd2c=
github.com/zyedidia/clipboard v0.0.0-20190823154308-241f98e9b197/go.mod h1:WDk3p8GiZV9+xFWlSo8qreeoLhW6Ik692rqXk+cNeRY=
github.com/zyedidia/clipboard v0.0.0-20200421031010-7c45b8673834 h1:0nOfq3JwYRiY3+nwfWVQYEaXDmGCQgj3RKoqTifLzP4=
github.com/zyedidia/clipboard v0.0.0-20200421031010-7c45b8673834/go.mod h1:zykFnZUXX0ErxqvYLUFEq7QDJKId8rmh2FgD0/Y8cjA=
github.com/zyedidia/glob v0.0.0-20170209203856-dd4023a66dc3 h1:oMHjjTLfGXVuyOQBYj5/td9WC0mw4g1xDBPovIqmHew=
github.com/zyedidia/glob v0.0.0-20170209203856-dd4023a66dc3/go.mod h1:YKbIYP//Eln8eDgAJGI3IDvR3s4Tv9Z9TGIOumiyQ5c=
github.com/zyedidia/go-shellquote v0.0.0-20200613203517-eccd813c0655 h1:Z3RhH6hvcSx7eX6Q/pP6YVsgea/1eMDG99vtWwi3nK4=
github.com/zyedidia/go-shellquote v0.0.0-20200613203517-eccd813c0655/go.mod h1:1sTqqO+kcYzZp43M5VsJe1tns9IzlSeC9jB6c2+o/5Y=
github.com/zyedidia/highlight v0.0.0-20170330143449-201131ce5cf5 h1:Zs6mpwXvlqpF9zHl5XaN0p5V4J9XvP+WBuiuXyIgqvc=
github.com/zyedidia/highlight v0.0.0-20170330143449-201131ce5cf5/go.mod h1:c1r+Ob9tUTPB0FKWO1+x+Hsc/zNa45WdGq7Y38Ybip0=
github.com/zyedidia/json5 v0.0.0-20200102012142-2da050b1a98d h1:zmDMkh22zXOB7gz8jFaI4GpI7llsPgzm38/jG0UgxjE=
@@ -54,10 +56,8 @@ github.com/zyedidia/poller v1.0.1 h1:Tt9S3AxAjXwWGNiC2TUdRJkQDZSzCBNVQ4xXiQ7440s
github.com/zyedidia/poller v1.0.1/go.mod h1:vZXJOHGDcuK08GXhF6IAY0ZFd2WcgOR5DOTp84Uk5eE=
github.com/zyedidia/pty v2.0.0+incompatible h1:Ou5vXL6tvjst+RV8sUFISbuKDnUJPhnpygApMFGweqw=
github.com/zyedidia/pty v2.0.0+incompatible/go.mod h1:4y9l9yJZNxRa7GB/fB+mmDmGkG3CqmzLf4vUxGGotEA=
github.com/zyedidia/tcell v1.4.4 h1:o34LXujNuSueuyTy+5eoQW+rQr8g0UbY8k1NczZyskQ=
github.com/zyedidia/tcell v1.4.4/go.mod h1:HhlbMSCcGX15rFDB+Q1Lk3pKEOocsCUAQC3zhZ9sadA=
github.com/zyedidia/tcell v1.4.5 h1:JFmOiWLxr3Fsk2vjRL3n8oRUoJeyrazGhkhZqW31kEY=
github.com/zyedidia/tcell v1.4.5/go.mod h1:HhlbMSCcGX15rFDB+Q1Lk3pKEOocsCUAQC3zhZ9sadA=
github.com/zyedidia/tcell v1.4.6 h1:8OYvZpUyqYQ3nigenBwOtnY3fXWEHekbm6QYchBeOxs=
github.com/zyedidia/tcell v1.4.6/go.mod h1:HhlbMSCcGX15rFDB+Q1Lk3pKEOocsCUAQC3zhZ9sadA=
github.com/zyedidia/terminal v0.0.0-20180726154117-533c623e2415 h1:752dTQ5OatJ9M5ULK2+9lor+nzyZz+LYDo3WGngg3Rc=
github.com/zyedidia/terminal v0.0.0-20180726154117-533c623e2415/go.mod h1:8leT8G0Cm8NoJHdrrKHyR9MirWoF4YW7pZh06B6H+1E=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -67,6 +67,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=

View File

@@ -663,7 +663,12 @@ func (h *BufPane) Autocomplete() bool {
return false
}
if !util.IsNonAlphaNumeric(h.Cursor.RuneUnder(h.Cursor.X)) {
if h.Cursor.X == 0 {
return false
}
r := h.Cursor.RuneUnder(h.Cursor.X)
prev := h.Cursor.RuneUnder(h.Cursor.X - 1)
if !util.IsAutocomplete(prev) || !util.IsNonAlphaNumeric(r) {
// don't autocomplete if cursor is on alpha numeric character (middle of a word)
return false
}
@@ -727,6 +732,7 @@ func (h *BufPane) Save() bool {
}
// SaveAsCB performs a save as and does a callback at the very end (after all prompts have been resolved)
// The callback is only called if the save was successful
func (h *BufPane) SaveAsCB(action string, callback func()) bool {
InfoBar.Prompt("Filename: ", "", "Save", nil, func(resp string, canceled bool) {
if !canceled {
@@ -757,6 +763,7 @@ func (h *BufPane) SaveAs() bool {
// This function saves the buffer to `filename` and changes the buffer's path and name
// to `filename` if the save is successful
// The callback is only called if the save was successful
func (h *BufPane) saveBufToFile(filename string, action string, callback func()) bool {
err := h.Buf.SaveAs(filename)
if err != nil {
@@ -769,6 +776,9 @@ func (h *BufPane) saveBufToFile(filename string, action string, callback func())
h.Buf.Path = filename
h.Buf.SetName(filename)
InfoBar.Message("Saved " + filename)
if callback != nil {
callback()
}
}
}
if h.Buf.Settings["autosu"].(bool) {
@@ -779,9 +789,6 @@ func (h *BufPane) saveBufToFile(filename string, action string, callback func())
saveWithSudo()
h.completeAction(action)
}
if callback != nil {
callback()
}
})
return false
}
@@ -792,9 +799,9 @@ func (h *BufPane) saveBufToFile(filename string, action string, callback func())
h.Buf.Path = filename
h.Buf.SetName(filename)
InfoBar.Message("Saved " + filename)
}
if callback != nil {
callback()
if callback != nil {
callback()
}
}
return true
}

View File

@@ -124,6 +124,8 @@ func BufMapKey(k Event, action string) {
break
}
}
// if the action changed the current pane, update the reference
h = MainTab().CurPane()
}
return true
}
@@ -330,7 +332,7 @@ func (h *BufPane) HandleEvent(event tcell.Event) {
switch e.Buttons() {
case tcell.Button1:
_, my := e.Position()
if h.Buf.Settings["statusline"].(bool) && my >= h.GetView().Y+h.GetView().Height-1 {
if h.Buf.Type.Kind != buffer.BTInfo.Kind && h.Buf.Settings["statusline"].(bool) && my >= h.GetView().Y+h.GetView().Height-1 {
cancel = true
}
case tcell.ButtonNone:

View File

@@ -339,7 +339,10 @@ func ReloadConfig() {
if err != nil {
screen.TermMessage(err)
}
config.InitGlobalSettings()
err = config.InitGlobalSettings()
if err != nil {
screen.TermMessage(err)
}
InitBindings()
InitCommands()
@@ -477,6 +480,7 @@ func SetGlobalOptionNative(option string, nativeValue interface{}) error {
if !local {
config.GlobalSettings[option] = nativeValue
config.ModifiedSettings[option] = true
if option == "colorscheme" {
// LoadSyntaxFiles()
@@ -701,6 +705,9 @@ func (h *BufPane) GotoCmd(args []string) {
InfoBar.Error(err)
return
}
if line < 0 {
line = h.Buf.LinesNum() + 1 + line
}
line = util.Clamp(line-1, 0, h.Buf.LinesNum()-1)
col = util.Clamp(col-1, 0, util.CharacterCount(h.Buf.LineBytes(line)))
h.Cursor.GotoLoc(buffer.Loc{col, line})
@@ -710,6 +717,9 @@ func (h *BufPane) GotoCmd(args []string) {
InfoBar.Error(err)
return
}
if line < 0 {
line = h.Buf.LinesNum() + 1 + line
}
line = util.Clamp(line-1, 0, h.Buf.LinesNum()-1)
h.Cursor.GotoLoc(buffer.Loc{0, line})
}

View File

@@ -35,6 +35,13 @@ func (h *RawPane) HandleEvent(event tcell.Event) {
}
h.Buf.Insert(h.Cursor.Loc, reflect.TypeOf(event).String()[7:])
switch e := event.(type) {
case *tcell.EventKey:
h.Buf.Insert(h.Cursor.Loc, fmt.Sprintf(": %s", e.Name()))
}
h.Buf.Insert(h.Cursor.Loc, fmt.Sprintf(": %q\n", event.EscSeq()))
h.Relocate()
}

View File

@@ -191,13 +191,22 @@ type Buffer struct {
StartCursor Loc
}
// NewBufferFromFile opens a new buffer using the given path
// It will also automatically handle `~`, and line/column with filename:l:c
// It will return an empty buffer if the path does not exist
// and an error if the file is a directory
func NewBufferFromFile(path string, btype BufType) (*Buffer, error) {
// NewBufferFromFileAtLoc opens a new buffer with a given cursor location
// If cursorLoc is {-1, -1} the location does not overwrite what the cursor location
// would otherwise be (start of file, or saved cursor position if `savecursor` is
// enabled)
func NewBufferFromFileAtLoc(path string, btype BufType, cursorLoc Loc) (*Buffer, error) {
var err error
filename, cursorPos := util.GetPathAndCursorPosition(path)
filename := path
if config.GetGlobalOption("parsecursor").(bool) && cursorLoc.X == -1 && cursorLoc.Y == -1 {
var cursorPos []string
filename, cursorPos = util.GetPathAndCursorPosition(filename)
cursorLoc, err = ParseCursorLocation(cursorPos)
if err != nil {
cursorLoc = Loc{-1, -1}
}
}
filename, err = util.ReplaceHome(filename)
if err != nil {
return nil, err
@@ -212,11 +221,6 @@ func NewBufferFromFile(path string, btype BufType) (*Buffer, error) {
defer file.Close()
cursorLoc, cursorerr := ParseCursorLocation(cursorPos)
if cursorerr != nil {
cursorLoc = Loc{-1, -1}
}
var buf *Buffer
if err != nil {
// File does not exist -- create an empty buffer with that name
@@ -228,6 +232,19 @@ func NewBufferFromFile(path string, btype BufType) (*Buffer, error) {
return buf, nil
}
// NewBufferFromFile opens a new buffer using the given path
// It will also automatically handle `~`, and line/column with filename:l:c
// It will return an empty buffer if the path does not exist
// and an error if the file is a directory
func NewBufferFromFile(path string, btype BufType) (*Buffer, error) {
return NewBufferFromFileAtLoc(path, btype, Loc{-1, -1})
}
// NewBufferFromStringAtLoc creates a new buffer containing the given string with a cursor loc
func NewBufferFromStringAtLoc(text, path string, btype BufType, cursorLoc Loc) *Buffer {
return NewBuffer(strings.NewReader(text), int64(len(text)), path, cursorLoc, btype)
}
// NewBufferFromString creates a new buffer containing the given string
func NewBufferFromString(text, path string, btype BufType) *Buffer {
return NewBuffer(strings.NewReader(text), int64(len(text)), path, Loc{-1, -1}, btype)
@@ -280,7 +297,21 @@ func NewBuffer(r io.Reader, size int64, path string, startcursor Loc, btype BufT
if !hasBackup {
reader := bufio.NewReader(transform.NewReader(r, enc.NewDecoder()))
b.LineArray = NewLineArray(uint64(size), FFAuto, reader)
var ff FileFormat = FFAuto
if size == 0 {
// for empty files, use the fileformat setting instead of
// autodetection
switch b.Settings["fileformat"] {
case "unix":
ff = FFUnix
case "dos":
ff = FFDos
}
}
b.LineArray = NewLineArray(uint64(size), ff, reader)
}
b.EventHandler = NewEventHandler(b.SharedBuffer, b.cursors)
@@ -806,19 +837,18 @@ func (b *Buffer) MoveLinesUp(start int, end int) {
}
l := string(b.LineBytes(start - 1))
if end == len(b.lines) {
b.Insert(
b.insert(
Loc{
util.CharacterCount(b.lines[end-1].data),
end - 1,
},
"\n"+l,
)
} else {
b.Insert(
Loc{0, end},
l+"\n",
[]byte{'\n'},
)
}
b.Insert(
Loc{0, end},
l+"\n",
)
b.Remove(
Loc{0, start - 1},
Loc{0, start},
@@ -827,7 +857,7 @@ func (b *Buffer) MoveLinesUp(start int, end int) {
// MoveLinesDown moves the range of lines down one row
func (b *Buffer) MoveLinesDown(start int, end int) {
if start < 0 || start >= end || end >= len(b.lines)-1 {
if start < 0 || start >= end || end >= len(b.lines) {
return
}
l := string(b.LineBytes(end))

View File

@@ -74,9 +74,6 @@ func (c *Cursor) GetVisualX() int {
bytes := c.buf.LineBytes(c.Y)
tabsize := int(c.buf.Settings["tabsize"].(float64))
if c.X > util.CharacterCount(bytes) {
c.X = util.CharacterCount(bytes) - 1
}
return util.StringWidth(bytes, c.X, tabsize)
}
@@ -242,6 +239,12 @@ func (c *Cursor) UpN(amount int) {
if c.X > util.CharacterCount(bytes) || (amount < 0 && proposedY == c.Y) {
c.X = util.CharacterCount(bytes)
c.StoreVisualX()
}
if c.X < 0 || (amount > 0 && proposedY == c.Y) {
c.X = 0
c.StoreVisualX()
}
c.Y = proposedY

View File

@@ -87,6 +87,8 @@ func NewLineArray(size uint64, endings FileFormat, reader io.Reader) *LineArray
br := bufio.NewReader(reader)
var loaded int
la.Endings = endings
n := 0
for {
data, err := br.ReadBytes('\n')

View File

@@ -96,7 +96,6 @@ func (b *Buffer) saveToFile(filename string, withSudo bool) error {
return errors.New("Save with sudo not supported on Windows")
}
b.UpdateRules()
if b.Settings["rmtrailingws"].(bool) {
for i, l := range b.lines {
leftover := util.CharacterCount(bytes.TrimRightFunc(l.data, unicode.IsSpace))
@@ -195,5 +194,6 @@ func (b *Buffer) saveToFile(filename string, withSudo bool) error {
absPath, _ := filepath.Abs(filename)
b.AbsPath = absPath
b.isModified = false
b.UpdateRules()
return err
}

View File

@@ -1,3 +1,4 @@
//go:generate go run runtime_generate.go ../../runtime/syntax ../../runtime
package config
import (
@@ -9,6 +10,8 @@ import (
"path/filepath"
"regexp"
"strings"
"github.com/zyedidia/micro/v2/internal/vfsutil"
)
const (
@@ -90,7 +93,7 @@ func (af assetFile) Name() string {
}
func (af assetFile) Data() ([]byte, error) {
return Asset(string(af))
return vfsutil.ReadFile(Assets, string(af))
}
func (nf namedFile) Name() string {
@@ -111,7 +114,10 @@ func AddRealRuntimeFile(fileType RTFiletype, file RuntimeFile) {
// AddRuntimeFilesFromDirectory registers each file from the given directory for
// the filetype which matches the file-pattern
func AddRuntimeFilesFromDirectory(fileType RTFiletype, directory, pattern string) {
files, _ := ioutil.ReadDir(directory)
files, err := ioutil.ReadDir(directory)
if err != nil {
return
}
for _, f := range files {
if ok, _ := filepath.Match(pattern, f.Name()); !f.IsDir() && ok {
fullPath := filepath.Join(directory, f.Name())
@@ -123,13 +129,13 @@ func AddRuntimeFilesFromDirectory(fileType RTFiletype, directory, pattern string
// AddRuntimeFilesFromAssets registers each file from the given asset-directory for
// the filetype which matches the file-pattern
func AddRuntimeFilesFromAssets(fileType RTFiletype, directory, pattern string) {
files, err := AssetDir(directory)
files, err := vfsutil.ReadDir(Assets, directory)
if err != nil {
return
}
for _, f := range files {
if ok, _ := path.Match(pattern, f); ok {
AddRuntimeFile(fileType, assetFile(path.Join(directory, f)))
if ok, _ := path.Match(pattern, f.Name()); ok {
AddRuntimeFile(fileType, assetFile(path.Join(directory, f.Name())))
}
}
}
@@ -156,11 +162,60 @@ func ListRealRuntimeFiles(fileType RTFiletype) []RuntimeFile {
return realFiles[fileType]
}
func addPlugin(dirname string, plugdir string, isID func(string) bool, vfs bool) {
var srcs []os.FileInfo
var err error
if vfs {
srcs, err = vfsutil.ReadDir(Assets, filepath.Join(plugdir, dirname))
} else {
srcs, err = ioutil.ReadDir(filepath.Join(plugdir, dirname))
}
if err != nil {
return
}
p := new(Plugin)
p.Name = dirname
p.DirName = dirname
p.Default = vfs
for _, f := range srcs {
if strings.HasSuffix(f.Name(), ".lua") {
if vfs {
p.Srcs = append(p.Srcs, assetFile(filepath.Join(plugdir, dirname, f.Name())))
} else {
p.Srcs = append(p.Srcs, realFile(filepath.Join(plugdir, dirname, f.Name())))
}
} else if strings.HasSuffix(f.Name(), ".json") {
var data []byte
var err error
if vfs {
data, err = vfsutil.ReadFile(Assets, filepath.Join(plugdir, dirname, f.Name()))
} else {
data, err = ioutil.ReadFile(filepath.Join(plugdir, dirname, f.Name()))
}
if err != nil {
continue
}
p.Info, err = NewPluginInfo(data)
if err != nil {
continue
}
p.Name = p.Info.Name
}
}
if !isID(p.Name) || len(p.Srcs) <= 0 {
log.Println(p.Name, "is not a plugin")
return
}
Plugins = append(Plugins, p)
}
// InitRuntimeFiles initializes all assets file and the config directory
func InitRuntimeFiles() {
add := func(fileType RTFiletype, dir, pattern string) {
AddRuntimeFilesFromDirectory(fileType, filepath.Join(ConfigDir, dir), pattern)
AddRuntimeFilesFromAssets(fileType, path.Join("runtime", dir), pattern)
AddRuntimeFilesFromAssets(fileType, dir, pattern)
}
add(RTColorscheme, "colorschemes", "*.micro")
@@ -179,68 +234,24 @@ func InitRuntimeFiles() {
// Search ConfigDir for plugin-scripts
plugdir := filepath.Join(ConfigDir, "plug")
files, _ := ioutil.ReadDir(plugdir)
files, err := ioutil.ReadDir(plugdir)
isID := regexp.MustCompile(`^[_A-Za-z0-9]+$`).MatchString
for _, d := range files {
if d.IsDir() {
srcs, _ := ioutil.ReadDir(filepath.Join(plugdir, d.Name()))
p := new(Plugin)
p.Name = d.Name()
p.DirName = d.Name()
for _, f := range srcs {
if strings.HasSuffix(f.Name(), ".lua") {
p.Srcs = append(p.Srcs, realFile(filepath.Join(plugdir, d.Name(), f.Name())))
} else if strings.HasSuffix(f.Name(), ".json") {
data, err := ioutil.ReadFile(filepath.Join(plugdir, d.Name(), f.Name()))
if err != nil {
continue
}
p.Info, err = NewPluginInfo(data)
if err != nil {
continue
}
p.Name = p.Info.Name
}
if err == nil {
for _, d := range files {
if d.IsDir() {
addPlugin(d.Name(), plugdir, isID, false)
}
if !isID(p.Name) || len(p.Srcs) <= 0 {
log.Println(p.Name, "is not a plugin")
continue
}
Plugins = append(Plugins, p)
}
}
plugdir = filepath.Join("runtime", "plugins")
if files, err := AssetDir(plugdir); err == nil {
plugdir = "plugins"
files, err = vfsutil.ReadDir(Assets, plugdir)
if err == nil {
for _, d := range files {
if srcs, err := AssetDir(filepath.Join(plugdir, d)); err == nil {
p := new(Plugin)
p.Name = d
p.DirName = d
p.Default = true
for _, f := range srcs {
if strings.HasSuffix(f, ".lua") {
p.Srcs = append(p.Srcs, assetFile(filepath.Join(plugdir, d, f)))
} else if strings.HasSuffix(f, ".json") {
data, err := Asset(filepath.Join(plugdir, d, f))
if err != nil {
continue
}
p.Info, err = NewPluginInfo(data)
if err != nil {
continue
}
p.Name = p.Info.Name
}
}
if !isID(p.Name) || len(p.Srcs) <= 0 {
log.Println(p.Name, "is not a plugin")
continue
}
Plugins = append(Plugins, p)
if d.IsDir() {
addPlugin(d.Name(), plugdir, isID, true)
}
}
}
@@ -277,7 +288,7 @@ func PluginAddRuntimeFile(plugin string, filetype RTFiletype, filePath string) e
if _, err := os.Stat(fullpath); err == nil {
AddRealRuntimeFile(filetype, realFile(fullpath))
} else {
fullpath = path.Join("runtime", "plugins", pldir, filePath)
fullpath = path.Join("plugins", pldir, filePath)
AddRuntimeFile(filetype, assetFile(fullpath))
}
return nil
@@ -294,7 +305,7 @@ func PluginAddRuntimeFilesFromDirectory(plugin string, filetype RTFiletype, dire
if _, err := os.Stat(fullpath); err == nil {
AddRuntimeFilesFromDirectory(filetype, fullpath, pattern)
} else {
fullpath = path.Join("runtime", "plugins", pldir, directory)
fullpath = path.Join("plugins", pldir, directory)
AddRuntimeFilesFromAssets(filetype, fullpath, pattern)
}
return nil

File diff suppressed because one or more lines are too long

View File

@@ -1,14 +1,22 @@
// +build ignore
// This script generates the embedded runtime filesystem, and also creates
// syntax header metadata which makes loading syntax files at runtime faster
// Invoke as go run runtime_generate.go syntaxDir runtimeDir
package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"time"
yaml "gopkg.in/yaml.v2"
"github.com/shurcooL/vfsgen"
)
type HeaderYaml struct {
@@ -25,19 +33,6 @@ type Header struct {
HeaderRgx string
}
func main() {
if len(os.Args) > 1 {
os.Chdir(os.Args[1])
}
files, _ := ioutil.ReadDir(".")
for _, f := range files {
fname := f.Name()
if strings.HasSuffix(fname, ".yaml") {
convert(fname[:len(fname)-5])
}
}
}
func convert(name string) {
filename := name + ".yaml"
var hdr HeaderYaml
@@ -61,14 +56,57 @@ func encode(name string, c HeaderYaml) {
}
func decode(name string) Header {
start := time.Now()
data, _ := ioutil.ReadFile(name + ".hdr")
strs := bytes.Split(data, []byte{'\n'})
var hdr Header
hdr.FileType = string(strs[0])
hdr.FNameRgx = string(strs[1])
hdr.HeaderRgx = string(strs[2])
fmt.Printf("took %v\n", time.Since(start))
return hdr
}
func main() {
orig, err := os.Getwd()
if err != nil {
log.Fatalln("Couldn't get cwd")
return
}
if len(os.Args) < 2 {
log.Fatalln("Not enough arguments")
}
syntaxDir := os.Args[1]
assetDir := os.Args[2]
os.Chdir(syntaxDir)
files, _ := ioutil.ReadDir(".")
// first remove all existing header files (clean the directory)
for _, f := range files {
fname := f.Name()
if strings.HasSuffix(fname, ".hdr") {
os.Remove(fname)
}
}
// now create a header file for each yaml
for _, f := range files {
fname := f.Name()
if strings.HasSuffix(fname, ".yaml") {
convert(fname[:len(fname)-5])
}
}
// create the assets_vfsdata.go file for embedding in the binary
os.Chdir(orig)
var assets http.FileSystem = http.Dir(assetDir)
err = vfsgen.Generate(assets, vfsgen.Options{
PackageName: "config",
VariableName: "Assets",
})
if err != nil {
log.Fatalln(err)
}
}

View File

@@ -3,6 +3,7 @@ package config
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -27,9 +28,14 @@ var (
// This is the raw parsed json
parsedSettings map[string]interface{}
// ModifiedSettings is a map of settings which should be written to disk
// because they have been modified by the user in this session
ModifiedSettings map[string]bool
)
func init() {
ModifiedSettings = make(map[string]bool)
parsedSettings = make(map[string]interface{})
}
@@ -75,16 +81,33 @@ func ReadSettings() error {
return nil
}
func verifySetting(option string, value reflect.Type, def reflect.Type) bool {
var interfaceArr []interface{}
switch option {
case "pluginrepos", "pluginchannels":
return value.AssignableTo(reflect.TypeOf(interfaceArr))
default:
return def.AssignableTo(value)
}
}
// InitGlobalSettings initializes the options map and sets all options to their default values
// Must be called after ReadSettings
func InitGlobalSettings() {
func InitGlobalSettings() error {
var err error
GlobalSettings = DefaultGlobalSettings()
for k, v := range parsedSettings {
if !strings.HasPrefix(reflect.TypeOf(v).String(), "map") {
if _, ok := GlobalSettings[k]; ok && !verifySetting(k, reflect.TypeOf(v), reflect.TypeOf(GlobalSettings[k])) {
err = errors.New(fmt.Sprintf("Global Error: setting '%s' has incorrect type (%s), using default value: %v (%s)", k, reflect.TypeOf(v), GlobalSettings[k], reflect.TypeOf(GlobalSettings[k])))
continue
}
GlobalSettings[k] = v
}
}
return err
}
// InitLocalSettings scans the json in settings.json and sets the options locally based
@@ -97,6 +120,10 @@ func InitLocalSettings(settings map[string]interface{}, path string) error {
if strings.HasPrefix(k, "ft:") {
if settings["filetype"].(string) == k[3:] {
for k1, v1 := range v.(map[string]interface{}) {
if _, ok := settings[k1]; ok && !verifySetting(k1, reflect.TypeOf(v1), reflect.TypeOf(settings[k1])) {
parseError = errors.New(fmt.Sprintf("Error: setting '%s' has incorrect type (%s), using default value: %v (%s)", k, reflect.TypeOf(v1), settings[k1], reflect.TypeOf(settings[k1])))
continue
}
settings[k1] = v1
}
}
@@ -109,6 +136,10 @@ func InitLocalSettings(settings map[string]interface{}, path string) error {
if g.MatchString(path) {
for k1, v1 := range v.(map[string]interface{}) {
if _, ok := settings[k1]; ok && !verifySetting(k1, reflect.TypeOf(v1), reflect.TypeOf(settings[k1])) {
parseError = errors.New(fmt.Sprintf("Error: setting '%s' has incorrect type (%s), using default value: %v (%s)", k, reflect.TypeOf(v1), settings[k1], reflect.TypeOf(settings[k1])))
continue
}
settings[k1] = v1
}
}
@@ -122,8 +153,25 @@ func InitLocalSettings(settings map[string]interface{}, path string) error {
func WriteSettings(filename string) error {
var err error
if _, e := os.Stat(ConfigDir); e == nil {
defaults := DefaultGlobalSettings()
// remove any options froms parsedSettings that have since been marked as default
for k, v := range parsedSettings {
if !strings.HasPrefix(reflect.TypeOf(v).String(), "map") {
cur, okcur := GlobalSettings[k]
if def, ok := defaults[k]; ok && okcur && reflect.DeepEqual(cur, def) {
delete(parsedSettings, k)
}
}
}
// add any options to parsedSettings that have since been marked as non-default
for k, v := range GlobalSettings {
parsedSettings[k] = v
if def, ok := defaults[k]; !ok || !reflect.DeepEqual(v, def) {
if _, wr := ModifiedSettings[k]; wr {
parsedSettings[k] = v
}
}
}
txt, _ := json.MarshalIndent(parsedSettings, "", " ")
@@ -132,10 +180,23 @@ func WriteSettings(filename string) error {
return err
}
// OverwriteSettings writes the current settings to settings.json and
// resets any user configuration of local settings present in settings.json
func OverwriteSettings(filename string) error {
settings := make(map[string]interface{})
var err error
if _, e := os.Stat(ConfigDir); e == nil {
txt, _ := json.MarshalIndent(GlobalSettings, "", " ")
defaults := DefaultGlobalSettings()
for k, v := range GlobalSettings {
if def, ok := defaults[k]; !ok || !reflect.DeepEqual(v, def) {
if _, wr := ModifiedSettings[k]; wr {
settings[k] = v
}
}
}
txt, _ := json.MarshalIndent(settings, "", " ")
err = ioutil.WriteFile(filename, append(txt, '\n'), 0644)
}
return err
@@ -203,6 +264,7 @@ var defaultCommonSettings = map[string]interface{}{
"readonly": false,
"rmtrailingws": false,
"ruler": true,
"relativeruler": false,
"savecursor": false,
"saveundo": false,
"scrollbar": false,
@@ -253,6 +315,7 @@ var DefaultGlobalOnlySettings = map[string]interface{}{
"infobar": true,
"keymenu": false,
"mouse": true,
"parsecursor": false,
"paste": false,
"savehistory": true,
"sucmd": "sudo",

View File

@@ -335,7 +335,14 @@ func (w *BufWindow) drawDiffGutter(backgroundStyle tcell.Style, softwrapped bool
}
func (w *BufWindow) drawLineNum(lineNumStyle tcell.Style, softwrapped bool, maxLineNumLength int, vloc *buffer.Loc, bloc *buffer.Loc) {
lineNum := strconv.Itoa(bloc.Y + 1)
cursorLine := w.Buf.GetActiveCursor().Loc.Y
var lineInt int
if w.Buf.Settings["relativeruler"] == false || cursorLine == bloc.Y {
lineInt = bloc.Y + 1
} else {
lineInt = bloc.Y - cursorLine
}
lineNum := strconv.Itoa(util.Abs(lineInt))
// Write the spaces before the line number if necessary
for i := 0; i < maxLineNumLength-len(lineNum); i++ {
@@ -511,6 +518,13 @@ func (w *BufWindow) displayBuffer() {
draw := func(r rune, combc []rune, style tcell.Style, showcursor bool) {
if nColsBeforeStart <= 0 {
_, origBg, _ := style.Decompose()
_, defBg, _ := config.DefStyle.Decompose()
// syntax highlighting with non-default background takes precedence
// over cursor-line and color-column
dontOverrideBackground := origBg != defBg
for _, c := range cursors {
if c.HasSelection() &&
(bloc.GreaterEqual(c.CurSelection[0]) && bloc.LessThan(c.CurSelection[1]) ||
@@ -523,7 +537,7 @@ func (w *BufWindow) displayBuffer() {
}
}
if b.Settings["cursorline"].(bool) && w.active &&
if b.Settings["cursorline"].(bool) && w.active && !dontOverrideBackground &&
!c.HasSelection() && c.Y == bloc.Y {
if s, ok := config.Colorscheme["cursor-line"]; ok {
fg, _, _ := s.Decompose()
@@ -555,7 +569,7 @@ func (w *BufWindow) displayBuffer() {
}
if s, ok := config.Colorscheme["color-column"]; ok {
if colorcolumn != 0 && vloc.X-w.gutterOffset+w.StartCol == colorcolumn {
if colorcolumn != 0 && vloc.X-w.gutterOffset+w.StartCol == colorcolumn && !dontOverrideBackground {
fg, _, _ := s.Decompose()
style = style.Background(fg)
}
@@ -659,7 +673,8 @@ func (w *BufWindow) displayBuffer() {
}
if vloc.X != bufWidth {
draw(' ', nil, curStyle, true)
// Display newline within a selection
draw(' ', nil, config.DefStyle, true)
}
bloc.X = w.StartCol

View File

@@ -146,7 +146,7 @@ func (i *InfoBuf) DonePrompt(canceled bool) {
h := i.History[i.PromptType]
h[len(h)-1] = resp
}
i.PromptCallback = nil
// i.PromptCallback = nil
}
i.Replace(i.Start(), i.End(), "")
}

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"os"
"sync"
"unicode"
"github.com/zyedidia/micro/v2/internal/config"
"github.com/zyedidia/micro/v2/internal/util"
@@ -97,6 +98,10 @@ func ShowCursor(x, y int) {
// SetContent sets a cell at a point on the screen and makes sure that it is
// synced with the last cursor location
func SetContent(x, y int, mainc rune, combc []rune, style tcell.Style) {
if !unicode.IsPrint(mainc) {
mainc = '<27>'
}
Screen.SetContent(x, y, mainc, combc, style)
if util.FakeCursor && lastCursor.x == x && lastCursor.y == y {
lastCursor.r = mainc

View File

@@ -16,6 +16,16 @@ import (
// For rendering, micro will display the combining characters. It's not perfect
// but it's pretty good.
var minMark = rune(unicode.Mark.R16[0].Lo)
func isMark(r rune) bool {
// Fast path
if r < minMark {
return false
}
return unicode.In(r, unicode.Mark)
}
// DecodeCharacter returns the next character from an array of bytes
// A character is a rune along with any accompanying combining runes
func DecodeCharacter(b []byte) (rune, []rune, int) {
@@ -24,7 +34,7 @@ func DecodeCharacter(b []byte) (rune, []rune, int) {
c, s := utf8.DecodeRune(b)
var combc []rune
for unicode.In(c, unicode.Mark) {
for isMark(c) {
combc = append(combc, c)
size += s
@@ -43,7 +53,7 @@ func DecodeCharacterInString(str string) (rune, []rune, int) {
c, s := utf8.DecodeRuneInString(str)
var combc []rune
for unicode.In(c, unicode.Mark) {
for isMark(c) {
combc = append(combc, c)
size += s
@@ -61,7 +71,7 @@ func CharacterCount(b []byte) int {
for len(b) > 0 {
r, size := utf8.DecodeRune(b)
if !unicode.In(r, unicode.Mark) {
if !isMark(r) {
s++
}
@@ -77,7 +87,7 @@ func CharacterCountInString(str string) int {
s := 0
for _, r := range str {
if !unicode.In(r, unicode.Mark) {
if !isMark(r) {
s++
}
}

View File

@@ -418,6 +418,10 @@ func IsNonAlphaNumeric(c rune) bool {
return !unicode.IsLetter(c) && !unicode.IsNumber(c) && c != '_'
}
func IsAutocomplete(c rune) bool {
return c == '.' || !IsNonAlphaNumeric(c)
}
func ParseSpecial(s string) string {
return strings.Replace(s, "\\t", "\t", -1)
}

21
internal/vfsutil/file.go Normal file
View File

@@ -0,0 +1,21 @@
package vfsutil
import (
"net/http"
"os"
)
// File implements http.FileSystem using the native file system restricted to a
// specific file served at root.
//
// While the FileSystem.Open method takes '/'-separated paths, a File's string
// value is a filename on the native file system, not a URL, so it is separated
// by filepath.Separator, which isn't necessarily '/'.
type File string
func (f File) Open(name string) (http.File, error) {
if name != "/" {
return nil, &os.PathError{Op: "open", Path: name, Err: os.ErrNotExist}
}
return os.Open(string(f))
}

View File

@@ -0,0 +1,39 @@
// Package vfsutil implements some I/O utility functions for http.FileSystem.
package vfsutil
import (
"io/ioutil"
"net/http"
"os"
)
// ReadDir reads the contents of the directory associated with file and
// returns a slice of FileInfo values in directory order.
func ReadDir(fs http.FileSystem, name string) ([]os.FileInfo, error) {
f, err := fs.Open(name)
if err != nil {
return nil, err
}
defer f.Close()
return f.Readdir(0)
}
// Stat returns the FileInfo structure describing file.
func Stat(fs http.FileSystem, name string) (os.FileInfo, error) {
f, err := fs.Open(name)
if err != nil {
return nil, err
}
defer f.Close()
return f.Stat()
}
// ReadFile reads the file named by path from fs and returns the contents.
func ReadFile(fs http.FileSystem, path string) ([]byte, error) {
rc, err := fs.Open(path)
if err != nil {
return nil, err
}
defer rc.Close()
return ioutil.ReadAll(rc)
}

146
internal/vfsutil/walk.go Normal file
View File

@@ -0,0 +1,146 @@
package vfsutil
import (
"io"
"net/http"
"os"
pathpkg "path"
"path/filepath"
"sort"
)
// Walk walks the filesystem rooted at root, calling walkFn for each file or
// directory in the filesystem, including root. All errors that arise visiting files
// and directories are filtered by walkFn. The files are walked in lexical
// order.
func Walk(fs http.FileSystem, root string, walkFn filepath.WalkFunc) error {
info, err := Stat(fs, root)
if err != nil {
return walkFn(root, nil, err)
}
return walk(fs, root, info, walkFn)
}
// readDirNames reads the directory named by dirname and returns
// a sorted list of directory entries.
func readDirNames(fs http.FileSystem, dirname string) ([]string, error) {
fis, err := ReadDir(fs, dirname)
if err != nil {
return nil, err
}
names := make([]string, len(fis))
for i := range fis {
names[i] = fis[i].Name()
}
sort.Strings(names)
return names, nil
}
// walk recursively descends path, calling walkFn.
func walk(fs http.FileSystem, path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
err := walkFn(path, info, nil)
if err != nil {
if info.IsDir() && err == filepath.SkipDir {
return nil
}
return err
}
if !info.IsDir() {
return nil
}
names, err := readDirNames(fs, path)
if err != nil {
return walkFn(path, info, err)
}
for _, name := range names {
filename := pathpkg.Join(path, name)
fileInfo, err := Stat(fs, filename)
if err != nil {
if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
return err
}
} else {
err = walk(fs, filename, fileInfo, walkFn)
if err != nil {
if !fileInfo.IsDir() || err != filepath.SkipDir {
return err
}
}
}
}
return nil
}
// WalkFilesFunc is the type of the function called for each file or directory visited by WalkFiles.
// It's like filepath.WalkFunc, except it provides an additional ReadSeeker parameter for file being visited.
type WalkFilesFunc func(path string, info os.FileInfo, rs io.ReadSeeker, err error) error
// WalkFiles walks the filesystem rooted at root, calling walkFn for each file or
// directory in the filesystem, including root. In addition to FileInfo, it passes an
// ReadSeeker to walkFn for each file it visits.
func WalkFiles(fs http.FileSystem, root string, walkFn WalkFilesFunc) error {
file, info, err := openStat(fs, root)
if err != nil {
return walkFn(root, nil, nil, err)
}
return walkFiles(fs, root, info, file, walkFn)
}
// walkFiles recursively descends path, calling walkFn.
// It closes the input file after it's done with it, so the caller shouldn't.
func walkFiles(fs http.FileSystem, path string, info os.FileInfo, file http.File, walkFn WalkFilesFunc) error {
err := walkFn(path, info, file, nil)
file.Close()
if err != nil {
if info.IsDir() && err == filepath.SkipDir {
return nil
}
return err
}
if !info.IsDir() {
return nil
}
names, err := readDirNames(fs, path)
if err != nil {
return walkFn(path, info, nil, err)
}
for _, name := range names {
filename := pathpkg.Join(path, name)
file, fileInfo, err := openStat(fs, filename)
if err != nil {
if err := walkFn(filename, nil, nil, err); err != nil && err != filepath.SkipDir {
return err
}
} else {
err = walkFiles(fs, filename, fileInfo, file, walkFn)
// file is closed by walkFiles, so we don't need to close it here.
if err != nil {
if !fileInfo.IsDir() || err != filepath.SkipDir {
return err
}
}
}
}
return nil
}
// openStat performs Open and Stat and returns results, or first error encountered.
// The caller is responsible for closing the returned file when done.
func openStat(fs http.FileSystem, name string) (http.File, os.FileInfo, error) {
f, err := fs.Open(name)
if err != nil {
return nil, nil, err
}
fi, err := f.Stat()
if err != nil {
f.Close()
return nil, nil, err
}
return f, fi, nil
}

View File

@@ -0,0 +1,93 @@
package vfsutil_test
import (
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"github.com/shurcooL/httpfs/vfsutil"
"golang.org/x/tools/godoc/vfs/httpfs"
"golang.org/x/tools/godoc/vfs/mapfs"
)
func ExampleWalk() {
var fs http.FileSystem = httpfs.New(mapfs.New(map[string]string{
"zzz-last-file.txt": "It should be visited last.",
"a-file.txt": "It has stuff.",
"another-file.txt": "Also stuff.",
"folderA/entry-A.txt": "Alpha.",
"folderA/entry-B.txt": "Beta.",
}))
walkFn := func(path string, fi os.FileInfo, err error) error {
if err != nil {
log.Printf("can't stat file %s: %v\n", path, err)
return nil
}
fmt.Println(path)
return nil
}
err := vfsutil.Walk(fs, "/", walkFn)
if err != nil {
panic(err)
}
// Output:
// /
// /a-file.txt
// /another-file.txt
// /folderA
// /folderA/entry-A.txt
// /folderA/entry-B.txt
// /zzz-last-file.txt
}
func ExampleWalkFiles() {
var fs http.FileSystem = httpfs.New(mapfs.New(map[string]string{
"zzz-last-file.txt": "It should be visited last.",
"a-file.txt": "It has stuff.",
"another-file.txt": "Also stuff.",
"folderA/entry-A.txt": "Alpha.",
"folderA/entry-B.txt": "Beta.",
}))
walkFn := func(path string, fi os.FileInfo, r io.ReadSeeker, err error) error {
if err != nil {
log.Printf("can't stat file %s: %v\n", path, err)
return nil
}
fmt.Println(path)
if !fi.IsDir() {
b, err := ioutil.ReadAll(r)
if err != nil {
log.Printf("can't read file %s: %v\n", path, err)
return nil
}
fmt.Printf("%q\n", b)
}
return nil
}
err := vfsutil.WalkFiles(fs, "/", walkFn)
if err != nil {
panic(err)
}
// Output:
// /
// /a-file.txt
// "It has stuff."
// /another-file.txt
// "Also stuff."
// /folderA
// /folderA/entry-A.txt
// "Alpha."
// /folderA/entry-B.txt
// "Beta."
// /zzz-last-file.txt
// "It should be visited last."
}

View File

@@ -5,6 +5,16 @@ import (
"unicode/utf8"
)
var minMark = rune(unicode.Mark.R16[0].Lo)
func isMark(r rune) bool {
// Fast path
if r < minMark {
return false
}
return unicode.In(r, unicode.Mark)
}
// DecodeCharacter returns the next character from an array of bytes
// A character is a rune along with any accompanying combining runes
func DecodeCharacter(b []byte) (rune, []rune, int) {
@@ -13,7 +23,7 @@ func DecodeCharacter(b []byte) (rune, []rune, int) {
c, s := utf8.DecodeRune(b)
var combc []rune
for unicode.In(c, unicode.Mark) {
for isMark(c) {
combc = append(combc, c)
size += s
@@ -32,7 +42,7 @@ func DecodeCharacterInString(str string) (rune, []rune, int) {
c, s := utf8.DecodeRuneInString(str)
var combc []rune
for unicode.In(c, unicode.Mark) {
for isMark(c) {
combc = append(combc, c)
size += s
@@ -50,7 +60,7 @@ func CharacterCount(b []byte) int {
for len(b) > 0 {
r, size := utf8.DecodeRune(b)
if !unicode.In(r, unicode.Mark) {
if !isMark(r) {
s++
}
@@ -66,7 +76,7 @@ func CharacterCountInString(str string) int {
s := 0
for _, r := range str {
if !unicode.In(r, unicode.Mark) {
if !isMark(r) {
s++
}
}

View File

@@ -11,7 +11,7 @@ color-link todo "bold #cc7833,#2b2b2b"
color-link error "bold #cc7833,#2b2b2b"
color-link gutter-error "#cc7833,#11151C"
color-link indent-char "#414141,#2b2b2b"
color-link line-number "#a1a1a1,#353535"
color-link line-number "#a1a1a1,#232323"
color-link current-line-number "#e6e1dc,#2b2b2b"
color-link diff-added "#00AF00"
color-link diff-modified "#FFAF00"
@@ -19,8 +19,8 @@ color-link diff-deleted "#D70000"
color-link gutter-warning "#a5c261,#11151C"
color-link symbol "#edb753,#2b2b2b"
color-link identifier "#edb753,#2b2b2b"
color-link statusline "#a1a1a1,#414141"
color-link tabbar "bold #a1a1a1,#414141"
color-link statusline "#b1b1b1,#232323"
color-link tabbar "bold #b1b1b1,#232323"
color-link cursor-line "#353535"
color-link color-column "#353535"
color-link space "underline #e6e1dc,#2b2b2b"

View File

@@ -11,115 +11,115 @@ can change it!
| Key | Description of function |
|---------- |-------------------------------------------------------------------------------------------------- |
| Ctrl+E | Open a command prompt for running commands (see `> help commands` for a list of valid commands). |
| Ctrl-e | Open a command prompt for running commands (see `> help commands` for a list of valid commands). |
| Tab | In command prompt, it will autocomplete if possible. |
| Ctrl+B | Run a shell command (this will close micro while your command executes). |
| Ctrl-b | Run a shell command (this will close micro while your command executes). |
### Navigation
| Key | Description of function |
|---------------------------- |------------------------------------------------------------------------------------------ |
| Arrows | Move the cursor around |
| Shift+arrows | Move and select text |
| Alt(Ctrl on Mac)+LeftArrow | Move to the beginning of the current line |
| Alt(Ctrl on Mac)+RightArrow | Move to the end of the current line |
| Shift-arrows | Move and select text |
| Alt(Ctrl on Mac)-LeftArrow | Move to the beginning of the current line |
| Alt(Ctrl on Mac)-RightArrow | Move to the end of the current line |
| Home | Move to the beginning of text on the current line |
| End | Move to the end of the current line |
| Ctrl(Alt on Mac)+LeftArrow | Move cursor one word left |
| Ctrl(Alt on Mac)+RightArrow | Move cursor one word right |
| Alt+{ | Move cursor to previous empty line, or beginning of document |
| Alt+} | Move cursor to next empty line, or end of document |
| Ctrl(Alt on Mac)-LeftArrow | Move cursor one word left |
| Ctrl(Alt on Mac)-RightArrow | Move cursor one word right |
| Alt-{ | Move cursor to previous empty line, or beginning of document |
| Alt-} | Move cursor to next empty line, or end of document |
| PageUp | Move cursor up one page |
| PageDown | Move cursor down one page |
| Ctrl+Home or Ctrl+UpArrow | Move cursor to start of document |
| Ctrl+End or Ctrl+DownArrow | Move cursor to end of document |
| Ctrl+L | Jump to a line in the file (prompts with #) |
| Ctrl+W | Cycle between splits in the current tab (use `> vsplit` or `> hsplit` to create a split) |
| Ctrl-Home or Ctrl-UpArrow | Move cursor to start of document |
| Ctrl-End or Ctrl-DownArrow | Move cursor to end of document |
| Ctrl-l | Jump to a line in the file (prompts with #) |
| Ctrl-w | Cycle between splits in the current tab (use `> vsplit` or `> hsplit` to create a split) |
### Tabs
| Key | Description of function |
|-------- |------------------------- |
| Ctrl+T | Open a new tab |
| Alt+, | Previous tab |
| Alt+. | Next tab |
| Ctrl-t | Open a new tab |
| Alt-, | Previous tab |
| Alt-. | Next tab |
### Find Operations
| Key | Description of function |
|---------- |------------------------------------------ |
| Ctrl+F | Find (opens prompt) |
| Ctrl+N | Find next instance of current search |
| Ctrl+P | Find previous instance of current search |
| Ctrl-f | Find (opens prompt) |
| Ctrl-n | Find next instance of current search |
| Ctrl-p | Find previous instance of current search |
### File Operations
| Key | Description of function |
|---------- |------------------------------------------------------------------ |
| Ctrl+Q | Close current file (quits micro if this is the last file open) |
| Ctrl+O | Open a file (prompts for filename) |
| Ctrl+S | Save current file |
| Ctrl-q | Close current file (quits micro if this is the last file open) |
| Ctrl-o | Open a file (prompts for filename) |
| Ctrl-s | Save current file |
### Text operations
| Key | Description of function |
|------------------------------------ |------------------------------------------ |
| Ctrl(Alt on Mac)+Shift+RightArrow | Select word right |
| Ctrl(Alt on Mac)+Shift+LeftArrow | Select word left |
| Alt(Ctrl on Mac)+Shift+LeftArrow | Select to start of current line |
| Alt(Ctrl on Mac)+Shift+RightArrow | Select to end of current line |
| Shift+Home | Select to start of current line |
| Shift+End | Select to end of current line |
| Ctrl+Shift+UpArrow | Select to start of file |
| Ctrl+Shift+DownArrow | Select to end of file |
| Ctrl+X | Cut selected text |
| Ctrl+C | Copy selected text |
| Ctrl+V | Paste |
| Ctrl+K | Cut current line |
| Ctrl+D | Duplicate current line |
| Ctrl+Z | Undo |
| Ctrl+Y | Redo |
| Alt+UpArrow | Move current line or selected lines up |
| Alt+DownArrow | Move current line of selected lines down |
| Alt+Backspace or Alt+Ctrl+H | Delete word left |
| Ctrl+A | Select all |
| Ctrl(Alt on Mac)-Shift-RightArrow | Select word right |
| Ctrl(Alt on Mac)-Shift-LeftArrow | Select word left |
| Alt(Ctrl on Mac)-Shift-LeftArrow | Select to start of current line |
| Alt(Ctrl on Mac)-Shift-RightArrow | Select to end of current line |
| Shift-Home | Select to start of current line |
| Shift-End | Select to end of current line |
| Ctrl-Shift-UpArrow | Select to start of file |
| Ctrl-Shift-DownArrow | Select to end of file |
| Ctrl-x | Cut selected text |
| Ctrl-c | Copy selected text |
| Ctrl-v | Paste |
| Ctrl-k | Cut current line |
| Ctrl-d | Duplicate current line |
| Ctrl-z | Undo |
| Ctrl-y | Redo |
| Alt-UpArrow | Move current line or selected lines up |
| Alt-DownArrow | Move current line of selected lines down |
| Alt-Backspace or Alt-Ctrl-h | Delete word left |
| Ctrl-a | Select all |
### Macros
| Key | Description of function |
|---------- |---------------------------------------------------------------------------------- |
| Ctrl+U | Toggle macro recording (press Ctrl+U to start recording and press again to stop) |
| Ctrl+J | Run latest recorded macro |
| Ctrl-u | Toggle macro recording (press Ctrl-u to start recording and press again to stop) |
| Ctrl-j | Run latest recorded macro |
### Multiple cursors
| Key | Description of function |
|------------------ |---------------------------------------------------------------------------------------------- |
| Alt+N | Create new multiple cursor from selection (will select current word if no current selection) |
| AltShiftUp | Spawn a new cursor on the line above the current one |
| AltShiftDown | Spawn a new cursor on the line below the current one |
| Alt+P | Remove latest multiple cursor |
| Alt+C | Remove all multiple cursors (cancel) |
| Alt+X | Skip multiple cursor selection |
| Alt+M | Spawn a new cursor at the beginning of every line in the current selection |
| Ctrl+MouseLeft | Place a multiple cursor at any location |
| Alt-n | Create new multiple cursor from selection (will select current word if no current selection) |
| Alt-Shift-Up | Spawn a new cursor on the line above the current one |
| Alt-Shift-Down | Spawn a new cursor on the line below the current one |
| Alt-p | Remove latest multiple cursor |
| Alt-c | Remove all multiple cursors (cancel) |
| Alt-x | Skip multiple cursor selection |
| Alt-m | Spawn a new cursor at the beginning of every line in the current selection |
| Ctrl-MouseLeft | Place a multiple cursor at any location |
### Other
| Key | Description of function |
|---------- |-------------------------------------------------------------------------------------- |
| Ctrl+G | Open help file |
| Ctrl+H | Backspace (old terminals do not support the backspace key and use Ctrl+H instead) |
| Ctrl+R | Toggle the line number ruler |
| Ctrl-g | Open help file |
| Ctrl-h | Backspace (old terminals do not support the backspace key and use Ctrl+H instead) |
| Ctrl-r | Toggle the line number ruler |
### Emacs style actions
| Key | Description of function |
|---------- |-------------------------- |
| Alt+F | Next word |
| Alt+B | Previous word |
| Alt+A | Move to start of line |
| Alt+E | Move to end of line |
| Alt-f | Next word |
| Alt-b | Previous word |
| Alt-a | Move to start of line |
| Alt-e | Move to end of line |
### Function keys.

View File

@@ -73,6 +73,12 @@ You can also bind a key to execute a command in command mode (see
}
```
**Note for macOS**: By default, macOS terminals do not forward alt events and
instead insert unicode characters. To fix this, do the following:
* iTerm2: select `Esc+` for `Left Option Key` in `Preferences->Profiles->Keys`.
* Terminal.app: Enable `Use Option key as Meta key` in `Preferences->Profiles->Keyboard`.
Now when you press `Alt-p` the `pwd` command will be executed which will show
your working directory in the infobar.

View File

@@ -117,12 +117,15 @@ Here are the available options:
default value: `false`
* `fileformat`: this determines what kind of line endings micro will use for
the file. UNIX line endings are just `\n` (linefeed) whereas dos line
the file. Unix line endings are just `\n` (linefeed) whereas dos line
endings are `\r\n` (carriage return + linefeed). The two possible values for
this option are `unix` and `dos`. The fileformat will be automatically
detected (when you open an existing file) and displayed on the statusline,
but this option is useful if you would like to change the line endings or if
you are starting a new file.
you are starting a new file. Changing this option while editing a file will
change its line endings. Opening a file with this option set will only have
an effect if the file is empty/newly created, because otherwise the fileformat
will be automatically detected from the existing line endings.
default value: `unix`
@@ -178,7 +181,7 @@ Here are the available options:
default value: `true`
* `paste`: Treat characters sent from the terminal in a single chunk as a paste
* `paste`: treat characters sent from the terminal in a single chunk as a paste
event rather than a series of manual key presses. If you are pasting using
the terminal keybinding (not Ctrl-v, which is micro's default paste
keybinding) then it is a good idea to enable this option during the paste
@@ -187,6 +190,16 @@ Here are the available options:
default value: `false`
* `parsecursor`: if enabled, this will cause micro to parse filenames such as
file.txt:10:5 as requesting to open `file.txt` with the cursor at line 10
and column 5. The column number can also be dropped to open the file at a
given line and column 0. Note that with this option enabled it is not possible
to open a file such as `file.txt:10:5`, where `:10:5` is part of the filename.
It is also possible to open a file with a certain cursor location by using the
`+LINE,COL` flag syntax. See `micro -help` for the command line options.
default value: `false`
* `pluginchannels`: list of URLs pointing to plugin channels for downloading and
installing plugins. A plugin channel consists of a json file with links to
plugin repos, which store information about plugin versions and download URLs.
@@ -214,6 +227,12 @@ Here are the available options:
default value: `true`
* `relativeruler`: make line numbers display relatively. If set to true, all lines except
for the line that the cursor is located will display the distance from the
cursor's line.
default value: `false`
* `savecursor`: remember where the cursor was last time the file was opened and
put it there when you open the file again. Information is saved to
`~/.config/micro/buffers/`

View File

@@ -6,24 +6,58 @@ local buffer = import("micro/buffer")
local ft = {}
ft["apacheconf"] = "# %s"
ft["bat"] = ":: %s"
ft["c"] = "// %s"
ft["c++"] = "// %s"
ft["cmake"] = "# %s"
ft["conf"] = "# %s"
ft["crystal"] = "# %s"
ft["css"] = "/* %s */"
ft["d"] = "// %s"
ft["dart"] = "// %s"
ft["dockerfile"] = "# %s"
ft["elm"] = "-- %s"
ft["fish"] = "# %s"
ft["gdscript"] = "# %s"
ft["glsl"] = "// %s"
ft["go"] = "// %s"
ft["python"] = "# %s"
ft["python3"] = "# %s"
ft["haskell"] = "-- %s"
ft["html"] = "<!-- %s -->"
ft["ini"] = "; %s"
ft["java"] = "// %s"
ft["javascript"] = "// %s"
ft["jinja2"] = "{# %s #}"
ft["julia"] = "# %s"
ft["kotlin"] = "// %s"
ft["lua"] = "-- %s"
ft["markdown"] = "<!-- %s -->"
ft["nginx"] = "# %s"
ft["nim"] = "# %s"
ft["objc"] = "// %s"
ft["pascal"] = "{ %s }"
ft["perl"] = "# %s"
ft["php"] = "// %s"
ft["rust"] = "// %s"
ft["shell"] = "# %s"
ft["lua"] = "-- %s"
ft["javascript"] = "// %s"
ft["pony"] = "// %s"
ft["powershell"] = "# %s"
ft["proto"] = "// %s"
ft["python"] = "# %s"
ft["python3"] = "# %s"
ft["ruby"] = "# %s"
ft["d"] = "// %s"
ft["rust"] = "// %s"
ft["scala"] = "// %s"
ft["shell"] = "# %s"
ft["sql"] = "-- %s"
ft["swift"] = "// %s"
ft["elm"] = "-- %s"
ft["tex"] = "% %s"
ft["toml"] = "# %s"
ft["twig"] = "{# %s #}"
ft["v"] = "// %s"
ft["xml"] = "<!-- %s -->"
ft["yaml"] = "# %s"
ft["zig"] = "// %s"
ft["zscript"] = "// %s"
ft["zsh"] = "# %s"
function onBufferOpen(buf)
if buf.Settings["commenttype"] == nil then
@@ -38,7 +72,7 @@ end
function commentLine(bp, lineN)
local line = bp.Buf:Line(lineN)
local commentType = bp.Buf.Settings["commenttype"]
local commentRegex = "^%s*" .. commentType:gsub("%*", "%*"):gsub("%-", "%-"):gsub("%.", "%."):gsub("%+", "%+"):gsub("%]", "%]"):gsub("%[", "%["):gsub("%%s", "(.*)")
local commentRegex = "^%s*" .. commentType:gsub("%%","%%%%"):gsub("%$","%$"):gsub("%)","%)"):gsub("%(","%("):gsub("%?","%?"):gsub("%*", "%*"):gsub("%-", "%-"):gsub("%.", "%."):gsub("%+", "%+"):gsub("%]", "%]"):gsub("%[", "%["):gsub("%%%%s", "(.*)")
local sel = -bp.Cursor.CurSelection
local curpos = -bp.Cursor.Loc
local index = string.find(commentType, "%%s") - 1
@@ -98,7 +132,8 @@ function comment(bp, args)
end
function trim(s)
return (s:gsub("^%s*(.-)%s*$", "%1"))
local trimmed = s:gsub("^%s*(.-)%s*$", "%1"):gsub("%%","%%%%")
return trimmed
end
function string.starts(String,Start)

View File

@@ -23,23 +23,58 @@ selected.
The comment type will be auto detected based on the filetype,
but it is only available for certain filetypes:
* apacheconf: `# %s`
* bat: `:: %s`
* c: `// %s`
* c++: `// %s`
* cmake: `# %s`
* conf: `# %s`
* crystal: `# %s`
* css: `/* %s */`
* d: `// %s`
* dart: `// %s`
* dockerfile: `# %s`
* elm: `-- %s`
* fish: `# %s`
* gdscript: `# %s`
* glsl: `// %s`
* go: `// %s`
* haskell: `-- %s`
* html: `<!-- %s -->`
* ini: `; %s`
* java: `// %s`
* javascript: `// %s`
* jinja2: `{# %s #}`
* julia: `# %s`
* kotlin: `// %s`
* lua: `-- %s`
* markdown: `<!-- %s -->`
* nginx: `# %s`
* nim: `# %s`
* objc: `// %s`
* pascal: `{ %s }`
* perl: `# %s`
* php: `// %s`
* pony: `// %s`
* powershell: `# %s`
* proto: `// %s`
* python: `# %s`
* python3: `# %s`
* ruby: `# %s`
* rust: `// %s`
* scala: `// %s`
* shell: `# %s`
* sql: `-- %s`
* swift: `// %s`
* tex: `% %s`
* toml: `# %s`
* twig: `{# %s #}`
* v: `// %s`
* xml: `<!-- %s -->`
* yaml: `# %s`
* zig: `// %s`
* zscript: `// %s`
* zsh: `# %s`
If your filetype is not available here, you can simply modify
the `commenttype` option:
@@ -57,4 +92,3 @@ Or in your `settings.json`:
}
}
```

View File

@@ -18,7 +18,7 @@ rules:
# definitions
- identifier: "def [a-zA-Z_0-9]+"
# keywords
- statement: "\\b(and|as|assert|await|break|class|continue|def|del|elif|else|except|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|raise|return|try|while|with|yield)\\b"
- statement: "\\b(and|as|assert|async|await|break|class|continue|def|del|elif|else|except|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|raise|return|try|while|with|yield)\\b"
# decorators
- brightgreen: "@.*[(]"
# operators

View File

@@ -1,8 +1,8 @@
filetype: shell
detect:
filename: "(\\.sh$|\\.bash|\\.ash|\\.bashrc|bashrc|\\.bash_aliases|bash_aliases|\\.bash_functions|bash_functions|\\.bash_profile|bash_profile|\\.profile|profile|Pkgfile|pkgmk.conf|profile|rc.conf|PKGBUILD|.ebuild\\$|APKBUILD)"
header: "^#!.*/(env +)?(ba)?(a)?sh( |$)"
filename: "(\\.sh$|\\.bash|\\.ash|bashrc|bash_aliases|bash_functions|profile|bash-fc\\.|Pkgfile|pkgmk.conf|rc.conf|PKGBUILD|.ebuild\\$|APKBUILD)"
header: "^#!.*/(env +)?(ba)?(a)?(mk)?sh( |$)"
rules:
# Numbers

View File

@@ -4,39 +4,53 @@ detect:
filename: "\\.toml"
rules:
- statement: "(.*)[[:space:]]="
- special: "="
# Bracket thingies
- special: "(\\[|\\])"
# Numbers and strings
- constant.number: "\\b([0-9]+|0x[0-9a-fA-F]*)\\b|'.'"
- constant.number: "\\\\([0-7]{3}|x[A-Fa-f0-9]{2}|u[A-Fa-f0-9]{4}|U[A-Fa-f0-9]{8})"
# Punctuation
- symbol: '[=,\.]'
- symbol.brackets: '[{\[\]}]'
# Strings
- constant.string:
start: "\""
end: "\""
skip: "\\\\."
start: '"""'
end: '\"{3,5}'
skip: '\\.'
rules:
- constant.specialChar: "\\\\."
- constant.specialChar: '\\u[[:xdigit:]]{4}'
- constant.specialChar: '\\U[[:xdigit:]]{8}'
- constant.specialChar: '\\[btnfr"\\]'
- constant.string:
start: '"'
end: '"'
skip: '\\.'
rules:
- constant.specialChar: '\\u[[:xdigit:]]{4}'
- constant.specialChar: '\\U[[:xdigit:]]{8}'
- constant.specialChar: '\\[btnfr"\\]'
- constant.string:
start: "'''"
end: "'{3,5}"
rules: []
- constant.string:
start: "'"
end: "'"
skip: "\\\\."
rules:
- constant.specialChar: "\\\\."
- constant.string:
start: "`"
end: "`"
rules:
- constant.specialChar: "\\\\."
rules: []
# Integer
- constant.number: '[+-]?(\d+_)*\d+\b'
- constant.number: '(0x([[:xdigit:]]+_)*[[:xdigit:]]+|0o([0-7]_)*[0-7]+|0b([01]+_)*[01]+)'
# Float
- constant.number: '[+-]?(\d+_)*\d+\.(\d+_)*\d+'
- constant.number: '[+-]?(\d+_)*\d+(\.(\d+_)*\d+)?[Ee][+-]?(\d+_)*\d+'
- constant.number: '(\+|-)(inf|nan)'
# Bare key, keys starting with a digit or dash are ambiguous with numbers and are skipped
- identifier: '\b[A-Za-z_][A-Za-z0-9_-]*\b'
# Boolean and inf, nan without sign
- constant.bool.true: '\btrue\b'
- constant.bool.false: '\bfalse\b'
- constant.number: '\b(inf|nan)\b'
# Date and Time
- constant: '\d+-\d{2}-\d{2}([T ]\d{2}:\d{2}:\d{2}(\.\d+)?([+-]\d{2}:\d{2}|Z)?)?'
- constant: '\d{2}:\d{2}:\d{2}(\.\d+)?'
# Comments
- comment:
start: "#"
end: "$"
rules:
- todo: "(TODO|XXX|FIXME):?"

Submodule tools/go-bindata deleted from 9453701aa0