mirror of
https://github.com/zyedidia/micro.git
synced 2026-04-03 08:29:49 +09:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d845eefe3 | ||
|
|
d8576d0fe6 | ||
|
|
7ee77d56a6 | ||
|
|
eb6daab169 | ||
|
|
b0cd92b70f | ||
|
|
a929437490 | ||
|
|
cb66d22b94 | ||
|
|
d1af21f626 | ||
|
|
0500cc234d | ||
|
|
f7677549ea | ||
|
|
d5caf84788 | ||
|
|
e31f5ed26e | ||
|
|
3ef0267f0a | ||
|
|
d5ff785559 | ||
|
|
e222ed73b8 | ||
|
|
432fc7ed58 | ||
|
|
43b512fd77 | ||
|
|
980112c071 | ||
|
|
b0e7efe6a5 | ||
|
|
64638845e9 | ||
|
|
97f362b465 | ||
|
|
f1801f1958 | ||
|
|
443ede470d | ||
|
|
c4d4d5fb7d | ||
|
|
28e0e20651 | ||
|
|
9a10cac598 | ||
|
|
0a080ba03c | ||
|
|
3f0cd019d7 | ||
|
|
5d3dbde698 | ||
|
|
87ad67ada7 | ||
|
|
fba5e2bf36 | ||
|
|
2e9dabd434 | ||
|
|
c8c7ad57bd | ||
|
|
986faa783b | ||
|
|
f86f56a628 | ||
|
|
957650c3ee | ||
|
|
8ff7ec50ef | ||
|
|
48645907ec | ||
|
|
3cbbba534c | ||
|
|
3dcd01f8b8 | ||
|
|
e7bdcb093b | ||
|
|
810133d5a8 | ||
|
|
3d6b0c6dd6 |
22
.github/workflows/test.yaml
vendored
Normal file
22
.github/workflows/test.yaml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
on: [push, pull_request]
|
||||
name: Build and Test
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.19.x]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
make build
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
make test
|
||||
0
.gitmodules
vendored
0
.gitmodules
vendored
11
.travis.yml
11
.travis.yml
@@ -1,11 +0,0 @@
|
||||
language: go
|
||||
go:
|
||||
- "1.13.x"
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
- windows
|
||||
script:
|
||||
- go build ./cmd/micro
|
||||
- go test ./internal/...
|
||||
- go test ./cmd/...
|
||||
16
README.md
16
README.md
@@ -1,6 +1,6 @@
|
||||
<img alt="micro logo" src="./assets/micro-logo-drop.svg" width="500px"/>
|
||||
|
||||
[](https://travis-ci.org/zyedidia/micro)
|
||||

|
||||
[](https://goreportcard.com/report/github.com/zyedidia/micro)
|
||||
[](https://github.com/zyedidia/micro/releases)
|
||||
[](https://github.com/zyedidia/micro/blob/master/LICENSE)
|
||||
@@ -139,8 +139,10 @@ for other operating systems. These packages are not guaranteed to be up-to-date.
|
||||
|
||||
* Linux: Available in distro-specific package managers.
|
||||
* `dnf install micro` (Fedora).
|
||||
* `apt install micro` (Ubuntu and Debian).
|
||||
* `pacman -S micro` (Arch Linux).
|
||||
* `emerge app-editors/micro` (Gentoo).
|
||||
* `zypper install micro-editor` (SUSE)
|
||||
* `eopkg install micro` (Solus).
|
||||
* `pacstall -I micro` (Pacstall).
|
||||
* See [wiki](https://github.com/zyedidia/micro/wiki/Installing-Micro) for details about CRUX, Termux.
|
||||
@@ -201,6 +203,18 @@ If you are using macOS, you should consider using [iTerm2](http://iterm2.com/) i
|
||||
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>.
|
||||
|
||||
### WSL and Windows Console
|
||||
|
||||
If you use micro within WSL, it is highly recommended that you use the [Windows
|
||||
Terminal](https://apps.microsoft.com/store/detail/windows-terminal/9N0DX20HK701?hl=en-us&gl=us)
|
||||
instead of the default Windows Console.
|
||||
|
||||
If you must use Windows Console for some reason, note that there is a bug in
|
||||
Windows Console WSL that causes a font change whenever micro tries to access
|
||||
the external clipboard via powershell. To fix this, use an internal clipboard
|
||||
with `set clipboard internal` (though your system clipboard will no longer be
|
||||
available in micro).
|
||||
|
||||
### Colors and syntax highlighting
|
||||
|
||||
If you open micro and it doesn't seem like syntax highlighting is working, this is probably because
|
||||
|
||||
@@ -150,6 +150,7 @@ func luaImportMicroUtil() *lua.LTable {
|
||||
ulua.L.SetField(pkg, "Unzip", luar.New(ulua.L, util.Unzip))
|
||||
ulua.L.SetField(pkg, "Version", luar.New(ulua.L, util.Version))
|
||||
ulua.L.SetField(pkg, "SemVersion", luar.New(ulua.L, util.SemVersion))
|
||||
ulua.L.SetField(pkg, "HttpRequest", luar.New(ulua.L, util.HttpRequest))
|
||||
ulua.L.SetField(pkg, "CharacterCountInString", luar.New(ulua.L, util.CharacterCountInString))
|
||||
ulua.L.SetField(pkg, "RuneStr", luar.New(ulua.L, func(r rune) string {
|
||||
return string(r)
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"os/signal"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"sort"
|
||||
"strconv"
|
||||
"syscall"
|
||||
@@ -37,6 +38,7 @@ var (
|
||||
flagConfigDir = flag.String("config-dir", "", "Specify a custom location for the configuration directory")
|
||||
flagOptions = flag.Bool("options", false, "Show all option help")
|
||||
flagDebug = flag.Bool("debug", false, "Enable debug mode (prints debug info to ./log.txt)")
|
||||
flagProfile = flag.Bool("profile", false, "Enable CPU profiling (writes profile info to ./micro.prof)")
|
||||
flagPlugin = flag.String("plugin", "", "Plugin command")
|
||||
flagClean = flag.Bool("clean", false, "Clean configuration directory")
|
||||
optionFlags map[string]*string
|
||||
@@ -59,6 +61,9 @@ func InitFlags() {
|
||||
fmt.Println(" \tShow all option help")
|
||||
fmt.Println("-debug")
|
||||
fmt.Println(" \tEnable debug mode (enables logging to ./log.txt)")
|
||||
fmt.Println("-profile")
|
||||
fmt.Println(" \tEnable CPU profiling (writes profile info to ./micro.prof")
|
||||
fmt.Println(" \tso it can be analyzed later with \"go tool pprof micro.prof\")")
|
||||
fmt.Println("-version")
|
||||
fmt.Println(" \tShow the version number and information")
|
||||
|
||||
@@ -228,15 +233,21 @@ func main() {
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
// runtime.SetCPUProfileRate(400)
|
||||
// f, _ := os.Create("micro.prof")
|
||||
// pprof.StartCPUProfile(f)
|
||||
// defer pprof.StopCPUProfile()
|
||||
|
||||
var err error
|
||||
|
||||
InitFlags()
|
||||
|
||||
if *flagProfile {
|
||||
f, err := os.Create("micro.prof")
|
||||
if err != nil {
|
||||
log.Fatal("error creating CPU profile: ", err)
|
||||
}
|
||||
if err := pprof.StartCPUProfile(f); err != nil {
|
||||
log.Fatal("error starting CPU profile: ", err)
|
||||
}
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
InitLog()
|
||||
|
||||
err = config.InitConfigDir(*flagConfigDir)
|
||||
|
||||
4
go.mod
4
go.mod
@@ -11,11 +11,11 @@ require (
|
||||
github.com/sergi/go-diff v1.1.0
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb
|
||||
github.com/zyedidia/clipper v0.1.0
|
||||
github.com/zyedidia/clipper v0.1.1
|
||||
github.com/zyedidia/glob v0.0.0-20170209203856-dd4023a66dc3
|
||||
github.com/zyedidia/json5 v0.0.0-20200102012142-2da050b1a98d
|
||||
github.com/zyedidia/pty v1.1.20 // indirect
|
||||
github.com/zyedidia/tcell/v2 v2.0.9
|
||||
github.com/zyedidia/tcell/v2 v2.0.10-0.20221007181625-f562052bccb8 // indirect
|
||||
github.com/zyedidia/terminal v0.0.0-20180726154117-533c623e2415
|
||||
golang.org/x/text v0.3.2
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
|
||||
4
go.sum
4
go.sum
@@ -43,6 +43,8 @@ github.com/zyedidia/clipper v0.0.0-20220613212750-517cd4a6c524 h1:sWYUMHs1EAlsPE
|
||||
github.com/zyedidia/clipper v0.0.0-20220613212750-517cd4a6c524/go.mod h1:7YApPNiiTZTXdKKZG92G50qj6mnWEX975Sdu65J7YpQ=
|
||||
github.com/zyedidia/clipper v0.1.0 h1:e16nhM1RgL3HYcugcHRUpMya1K830TS5uo6LlPJHySg=
|
||||
github.com/zyedidia/clipper v0.1.0/go.mod h1:7YApPNiiTZTXdKKZG92G50qj6mnWEX975Sdu65J7YpQ=
|
||||
github.com/zyedidia/clipper v0.1.1 h1:HBgguFNDq/QmSQKBnhy4sMKzILINr139VEgAhftOUTw=
|
||||
github.com/zyedidia/clipper v0.1.1/go.mod h1:7YApPNiiTZTXdKKZG92G50qj6mnWEX975Sdu65J7YpQ=
|
||||
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-runewidth v0.0.12 h1:aHWj8qL3aH7caRzoPBJXe1pEaZBXHpKtfTuiBo5p74Q=
|
||||
@@ -61,6 +63,8 @@ github.com/zyedidia/pty v1.1.20 h1:mkZ5/UiEjZVMFzoXp8oyJAlbn3b380m5lvFrbx/NL/g=
|
||||
github.com/zyedidia/pty v1.1.20/go.mod h1:HWbpfrLoVM9FmU+/9NV+PzVQV8jSxgnQLk8fvx0q/i8=
|
||||
github.com/zyedidia/tcell/v2 v2.0.9 h1:FxXRkE62N0GPHES7EMLtp2rteYqC9r1kVid8vJN1kOE=
|
||||
github.com/zyedidia/tcell/v2 v2.0.9/go.mod h1:i4NNlquIQXFeNecrOgxDQQJdu+7LmTi3g62asvmwUws=
|
||||
github.com/zyedidia/tcell/v2 v2.0.10-0.20221007181625-f562052bccb8 h1:53ULv4mmLyQDnqbjVxanckP57WSreWHwTmlLJrJEutY=
|
||||
github.com/zyedidia/tcell/v2 v2.0.10-0.20221007181625-f562052bccb8/go.mod h1:i4NNlquIQXFeNecrOgxDQQJdu+7LmTi3g62asvmwUws=
|
||||
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=
|
||||
|
||||
@@ -4,12 +4,12 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
||||
shellquote "github.com/kballard/go-shellquote"
|
||||
"github.com/zyedidia/micro/v2/internal/buffer"
|
||||
"github.com/zyedidia/micro/v2/internal/clipboard"
|
||||
@@ -791,10 +791,27 @@ func (h *BufPane) SaveAsCB(action string, callback func()) bool {
|
||||
return
|
||||
}
|
||||
filename := strings.Join(args, " ")
|
||||
noPrompt := h.saveBufToFile(filename, action, callback)
|
||||
if noPrompt {
|
||||
h.completeAction(action)
|
||||
fileinfo, err := os.Stat(filename)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
noPrompt := h.saveBufToFile(filename, action, callback)
|
||||
if noPrompt {
|
||||
h.completeAction(action)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
InfoBar.YNPrompt(
|
||||
fmt.Sprintf("the file %s already exists in the directory, would you like to overwrite? Y/n", fileinfo.Name()),
|
||||
func(yes, canceled bool) {
|
||||
if yes && !canceled {
|
||||
noPrompt := h.saveBufToFile(filename, action, callback)
|
||||
if noPrompt {
|
||||
h.completeAction(action)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
})
|
||||
return false
|
||||
@@ -879,11 +896,10 @@ func (h *BufPane) Search(str string, useRegex bool, searchDown bool) error {
|
||||
h.Cursor.SetSelectionEnd(match[1])
|
||||
h.Cursor.OrigSelection[0] = h.Cursor.CurSelection[0]
|
||||
h.Cursor.OrigSelection[1] = h.Cursor.CurSelection[1]
|
||||
h.Cursor.GotoLoc(h.Cursor.CurSelection[1])
|
||||
h.GotoLoc(h.Cursor.CurSelection[1])
|
||||
h.Buf.LastSearch = str
|
||||
h.Buf.LastSearchRegex = useRegex
|
||||
h.Buf.HighlightSearch = h.Buf.Settings["hlsearch"].(bool)
|
||||
h.Relocate()
|
||||
} else {
|
||||
h.Cursor.ResetSelection()
|
||||
}
|
||||
@@ -905,12 +921,11 @@ func (h *BufPane) find(useRegex bool) bool {
|
||||
h.Cursor.SetSelectionEnd(match[1])
|
||||
h.Cursor.OrigSelection[0] = h.Cursor.CurSelection[0]
|
||||
h.Cursor.OrigSelection[1] = h.Cursor.CurSelection[1]
|
||||
h.Cursor.GotoLoc(match[1])
|
||||
h.GotoLoc(match[1])
|
||||
} else {
|
||||
h.Cursor.GotoLoc(h.searchOrig)
|
||||
h.GotoLoc(h.searchOrig)
|
||||
h.Cursor.ResetSelection()
|
||||
}
|
||||
h.Relocate()
|
||||
}
|
||||
}
|
||||
findCallback := func(resp string, canceled bool) {
|
||||
@@ -925,7 +940,7 @@ func (h *BufPane) find(useRegex bool) bool {
|
||||
h.Cursor.SetSelectionEnd(match[1])
|
||||
h.Cursor.OrigSelection[0] = h.Cursor.CurSelection[0]
|
||||
h.Cursor.OrigSelection[1] = h.Cursor.CurSelection[1]
|
||||
h.Cursor.GotoLoc(h.Cursor.CurSelection[1])
|
||||
h.GotoLoc(h.Cursor.CurSelection[1])
|
||||
h.Buf.LastSearch = resp
|
||||
h.Buf.LastSearchRegex = useRegex
|
||||
h.Buf.HighlightSearch = h.Buf.Settings["hlsearch"].(bool)
|
||||
@@ -936,7 +951,6 @@ func (h *BufPane) find(useRegex bool) bool {
|
||||
} else {
|
||||
h.Cursor.ResetSelection()
|
||||
}
|
||||
h.Relocate()
|
||||
}
|
||||
pattern := string(h.Cursor.GetSelection())
|
||||
if eventCallback != nil && pattern != "" {
|
||||
@@ -980,11 +994,10 @@ func (h *BufPane) FindNext() bool {
|
||||
h.Cursor.SetSelectionEnd(match[1])
|
||||
h.Cursor.OrigSelection[0] = h.Cursor.CurSelection[0]
|
||||
h.Cursor.OrigSelection[1] = h.Cursor.CurSelection[1]
|
||||
h.Cursor.Loc = h.Cursor.CurSelection[1]
|
||||
h.GotoLoc(h.Cursor.CurSelection[1])
|
||||
} else {
|
||||
h.Cursor.ResetSelection()
|
||||
}
|
||||
h.Relocate()
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1007,11 +1020,10 @@ func (h *BufPane) FindPrevious() bool {
|
||||
h.Cursor.SetSelectionEnd(match[1])
|
||||
h.Cursor.OrigSelection[0] = h.Cursor.CurSelection[0]
|
||||
h.Cursor.OrigSelection[1] = h.Cursor.CurSelection[1]
|
||||
h.Cursor.Loc = h.Cursor.CurSelection[1]
|
||||
h.GotoLoc(h.Cursor.CurSelection[1])
|
||||
} else {
|
||||
h.Cursor.ResetSelection()
|
||||
}
|
||||
h.Relocate()
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ func findSingleEvent(k string) (b Event, ok bool) {
|
||||
modSearch:
|
||||
for {
|
||||
switch {
|
||||
case strings.HasPrefix(k, "-"):
|
||||
case strings.HasPrefix(k, "-") && k != "-":
|
||||
// We optionally support dashes between modifiers
|
||||
k = k[1:]
|
||||
case strings.HasPrefix(k, "Ctrl") && k != "CtrlH":
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/zyedidia/micro/v2/internal/display"
|
||||
ulua "github.com/zyedidia/micro/v2/internal/lua"
|
||||
"github.com/zyedidia/micro/v2/internal/screen"
|
||||
"github.com/zyedidia/micro/v2/internal/util"
|
||||
"github.com/zyedidia/tcell/v2"
|
||||
)
|
||||
|
||||
@@ -235,10 +236,14 @@ type BufPane struct {
|
||||
|
||||
// remember original location of a search in case the search is canceled
|
||||
searchOrig buffer.Loc
|
||||
|
||||
// The pane may not yet be fully initialized after its creation
|
||||
// since we may not know the window geometry yet. In such case we finish
|
||||
// its initialization a bit later, after the initial resize.
|
||||
initialized bool
|
||||
}
|
||||
|
||||
// NewBufPane creates a new buffer pane with the given window.
|
||||
func NewBufPane(buf *buffer.Buffer, win display.BWindow, tab *Tab) *BufPane {
|
||||
func newBufPane(buf *buffer.Buffer, win display.BWindow, tab *Tab) *BufPane {
|
||||
h := new(BufPane)
|
||||
h.Buf = buf
|
||||
h.BWindow = win
|
||||
@@ -247,8 +252,13 @@ func NewBufPane(buf *buffer.Buffer, win display.BWindow, tab *Tab) *BufPane {
|
||||
h.Cursor = h.Buf.GetActiveCursor()
|
||||
h.mouseReleased = true
|
||||
|
||||
config.RunPluginFn("onBufPaneOpen", luar.New(ulua.L, h))
|
||||
return h
|
||||
}
|
||||
|
||||
// NewBufPane creates a new buffer pane with the given window.
|
||||
func NewBufPane(buf *buffer.Buffer, win display.BWindow, tab *Tab) *BufPane {
|
||||
h := newBufPane(buf, win, tab)
|
||||
h.finishInitialize()
|
||||
return h
|
||||
}
|
||||
|
||||
@@ -256,7 +266,25 @@ func NewBufPane(buf *buffer.Buffer, win display.BWindow, tab *Tab) *BufPane {
|
||||
// creates a buf window.
|
||||
func NewBufPaneFromBuf(buf *buffer.Buffer, tab *Tab) *BufPane {
|
||||
w := display.NewBufWindow(0, 0, 0, 0, buf)
|
||||
return NewBufPane(buf, w, tab)
|
||||
h := newBufPane(buf, w, tab)
|
||||
// Postpone finishing initializing the pane until we know the actual geometry
|
||||
// of the buf window.
|
||||
return h
|
||||
}
|
||||
|
||||
// TODO: make sure splitID and tab are set before finishInitialize is called
|
||||
func (h *BufPane) finishInitialize() {
|
||||
h.initialRelocate()
|
||||
h.initialized = true
|
||||
config.RunPluginFn("onBufPaneOpen", luar.New(ulua.L, h))
|
||||
}
|
||||
|
||||
// Resize resizes the pane
|
||||
func (h *BufPane) Resize(width, height int) {
|
||||
h.BWindow.Resize(width, height)
|
||||
if !h.initialized {
|
||||
h.finishInitialize()
|
||||
}
|
||||
}
|
||||
|
||||
// SetTab sets this pane's tab.
|
||||
@@ -301,7 +329,7 @@ func (h *BufPane) OpenBuffer(b *buffer.Buffer) {
|
||||
h.BWindow.SetBuffer(b)
|
||||
h.Cursor = b.GetActiveCursor()
|
||||
h.Resize(h.GetView().Width, h.GetView().Height)
|
||||
h.Relocate()
|
||||
h.initialRelocate()
|
||||
// Set mouseReleased to true because we assume the mouse is not being
|
||||
// pressed when the editor is opened
|
||||
h.mouseReleased = true
|
||||
@@ -311,6 +339,43 @@ func (h *BufPane) OpenBuffer(b *buffer.Buffer) {
|
||||
h.lastClickTime = time.Time{}
|
||||
}
|
||||
|
||||
// GotoLoc moves the cursor to a new location and adjusts the view accordingly.
|
||||
// Use GotoLoc when the new location may be far away from the current location.
|
||||
func (h *BufPane) GotoLoc(loc buffer.Loc) {
|
||||
sloc := h.SLocFromLoc(loc)
|
||||
d := h.Diff(h.SLocFromLoc(h.Cursor.Loc), sloc)
|
||||
|
||||
h.Cursor.GotoLoc(loc)
|
||||
|
||||
// If the new location is far away from the previous one,
|
||||
// ensure the cursor is at 25% of the window height
|
||||
height := h.BufView().Height
|
||||
if util.Abs(d) >= height {
|
||||
v := h.GetView()
|
||||
v.StartLine = h.Scroll(sloc, -height/4)
|
||||
h.ScrollAdjust()
|
||||
v.StartCol = 0
|
||||
}
|
||||
h.Relocate()
|
||||
}
|
||||
|
||||
func (h *BufPane) initialRelocate() {
|
||||
sloc := h.SLocFromLoc(h.Cursor.Loc)
|
||||
height := h.BufView().Height
|
||||
|
||||
// If the initial cursor location is far away from the beginning
|
||||
// of the buffer, ensure the cursor is at 25% of the window height
|
||||
v := h.GetView()
|
||||
if h.Diff(display.SLoc{0, 0}, sloc) < height {
|
||||
v.StartLine = display.SLoc{0, 0}
|
||||
} else {
|
||||
v.StartLine = h.Scroll(sloc, -height/4)
|
||||
h.ScrollAdjust()
|
||||
}
|
||||
v.StartCol = 0
|
||||
h.Relocate()
|
||||
}
|
||||
|
||||
// ID returns this pane's split id.
|
||||
func (h *BufPane) ID() uint64 {
|
||||
return h.splitID
|
||||
|
||||
@@ -722,7 +722,7 @@ func (h *BufPane) GotoCmd(args []string) {
|
||||
}
|
||||
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})
|
||||
h.GotoLoc(buffer.Loc{col, line})
|
||||
} else {
|
||||
line, err := strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
@@ -733,9 +733,8 @@ func (h *BufPane) GotoCmd(args []string) {
|
||||
line = h.Buf.LinesNum() + 1 + line
|
||||
}
|
||||
line = util.Clamp(line-1, 0, h.Buf.LinesNum()-1)
|
||||
h.Cursor.GotoLoc(buffer.Loc{0, line})
|
||||
h.GotoLoc(buffer.Loc{0, line})
|
||||
}
|
||||
h.Relocate()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -834,13 +833,11 @@ func (h *BufPane) ReplaceCmd(args []string) {
|
||||
|
||||
h.Cursor.SetSelectionStart(locs[0])
|
||||
h.Cursor.SetSelectionEnd(locs[1])
|
||||
h.Cursor.GotoLoc(locs[0])
|
||||
h.GotoLoc(locs[0])
|
||||
h.Buf.LastSearch = search
|
||||
h.Buf.LastSearchRegex = true
|
||||
h.Buf.HighlightSearch = h.Buf.Settings["hlsearch"].(bool)
|
||||
|
||||
h.Relocate()
|
||||
|
||||
InfoBar.YNPrompt("Perform replacement (y,n,esc)", func(yes, canceled bool) {
|
||||
if !canceled && yes {
|
||||
_, nrunes := h.Buf.ReplaceRegex(locs[0], locs[1], regex, replace)
|
||||
@@ -853,8 +850,7 @@ func (h *BufPane) ReplaceCmd(args []string) {
|
||||
h.Cursor.Loc = searchLoc
|
||||
nreplaced++
|
||||
} else if !canceled && !yes {
|
||||
searchLoc = locs[0]
|
||||
searchLoc.X += util.CharacterCount(replace)
|
||||
searchLoc = locs[1]
|
||||
} else if canceled {
|
||||
h.Cursor.ResetSelection()
|
||||
h.Buf.RelocateCursors()
|
||||
|
||||
@@ -148,7 +148,19 @@ func (t *TabList) Display() {
|
||||
var Tabs *TabList
|
||||
|
||||
func InitTabs(bufs []*buffer.Buffer) {
|
||||
Tabs = NewTabList(bufs)
|
||||
multiopen := config.GetGlobalOption("multiopen").(string)
|
||||
if multiopen == "tab" {
|
||||
Tabs = NewTabList(bufs)
|
||||
} else {
|
||||
Tabs = NewTabList(bufs[:1])
|
||||
for _, b := range bufs[1:] {
|
||||
if multiopen == "vsplit" {
|
||||
MainTab().CurPane().VSplitBuf(b)
|
||||
} else { // default hsplit
|
||||
MainTab().CurPane().HSplitBuf(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func MainTab() *Tab {
|
||||
|
||||
@@ -29,9 +29,11 @@ const LargeFileThreshold = 50000
|
||||
// closed afterwards.
|
||||
func overwriteFile(name string, enc encoding.Encoding, fn func(io.Writer) error, withSudo bool) (err error) {
|
||||
var writeCloser io.WriteCloser
|
||||
var screenb bool
|
||||
var cmd *exec.Cmd
|
||||
|
||||
if withSudo {
|
||||
cmd := exec.Command(config.GlobalSettings["sucmd"].(string), "dd", "bs=4k", "of="+name)
|
||||
cmd = exec.Command(config.GlobalSettings["sucmd"].(string), "dd", "bs=4k", "of="+name)
|
||||
|
||||
if writeCloser, err = cmd.StdinPipe(); err != nil {
|
||||
return
|
||||
@@ -44,13 +46,13 @@ func overwriteFile(name string, enc encoding.Encoding, fn func(io.Writer) error,
|
||||
cmd.Process.Kill()
|
||||
}()
|
||||
|
||||
defer func() {
|
||||
screenb := screen.TempFini()
|
||||
if e := cmd.Run(); e != nil && err == nil {
|
||||
err = e
|
||||
}
|
||||
screen.TempStart(screenb)
|
||||
}()
|
||||
screenb = screen.TempFini()
|
||||
// need to start the process now, otherwise when we flush the file
|
||||
// contents to its stdin it might hang because the kernel's pipe size
|
||||
// is too small to handle the full file contents all at once
|
||||
if e := cmd.Start(); e != nil && err == nil {
|
||||
return err
|
||||
}
|
||||
} else if writeCloser, err = os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
|
||||
return
|
||||
}
|
||||
@@ -63,6 +65,15 @@ func overwriteFile(name string, enc encoding.Encoding, fn func(io.Writer) error,
|
||||
err = e
|
||||
}
|
||||
|
||||
if withSudo {
|
||||
// wait for dd to finish and restart the screen if we used sudo
|
||||
err := cmd.Wait()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
screen.TempStart(screenb)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,16 @@ func (b *Buffer) SetOptionNative(option string, nativeValue interface{}) error {
|
||||
} else if option == "statusline" {
|
||||
screen.Redraw()
|
||||
} else if option == "filetype" {
|
||||
config.InitRuntimeFiles()
|
||||
err := config.ReadSettings()
|
||||
if err != nil {
|
||||
screen.TermMessage(err)
|
||||
}
|
||||
err = config.InitGlobalSettings()
|
||||
if err != nil {
|
||||
screen.TermMessage(err)
|
||||
}
|
||||
config.InitLocalSettings(b.Settings, b.Path)
|
||||
b.UpdateRules()
|
||||
} else if option == "fileformat" {
|
||||
switch b.Settings["fileformat"].(string) {
|
||||
|
||||
@@ -51,6 +51,7 @@ var optionValidators = map[string]optionValidator{
|
||||
"colorcolumn": validateNonNegativeValue,
|
||||
"fileformat": validateLineEnding,
|
||||
"encoding": validateEncoding,
|
||||
"multiopen": validateMultiOpen,
|
||||
}
|
||||
|
||||
func ReadSettings() error {
|
||||
@@ -330,9 +331,11 @@ var DefaultGlobalOnlySettings = map[string]interface{}{
|
||||
"colorscheme": "default",
|
||||
"divchars": "|-",
|
||||
"divreverse": true,
|
||||
"fakecursor": false,
|
||||
"infobar": true,
|
||||
"keymenu": false,
|
||||
"mouse": true,
|
||||
"multiopen": "tab",
|
||||
"parsecursor": false,
|
||||
"paste": false,
|
||||
"pluginchannels": []string{"https://raw.githubusercontent.com/micro-editor/plugin-channel/master/channel.json"},
|
||||
@@ -491,3 +494,19 @@ func validateEncoding(option string, value interface{}) error {
|
||||
_, err := htmlindex.Get(value.(string))
|
||||
return err
|
||||
}
|
||||
|
||||
func validateMultiOpen(option string, value interface{}) error {
|
||||
val, ok := value.(string)
|
||||
|
||||
if !ok {
|
||||
return errors.New("Expected string type for multiopen")
|
||||
}
|
||||
|
||||
switch val {
|
||||
case "tab", "hsplit", "vsplit":
|
||||
default:
|
||||
return errors.New(option + " must be 'tab', 'hsplit', or 'vsplit'")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package display
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"unicode"
|
||||
|
||||
runewidth "github.com/mattn/go-runewidth"
|
||||
"github.com/zyedidia/micro/v2/internal/buffer"
|
||||
@@ -53,8 +54,10 @@ func (w *BufWindow) SetBuffer(b *buffer.Buffer) {
|
||||
} else {
|
||||
w.StartLine.Row = 0
|
||||
}
|
||||
w.Relocate()
|
||||
}
|
||||
|
||||
if option == "softwrap" || option == "wordwrap" {
|
||||
w.Relocate()
|
||||
for _, c := range w.Buf.GetCursors() {
|
||||
c.LastVisualX = c.GetVisualX()
|
||||
}
|
||||
@@ -81,12 +84,6 @@ func (w *BufWindow) Resize(width, height int) {
|
||||
w.updateDisplayInfo()
|
||||
|
||||
w.Relocate()
|
||||
|
||||
if w.Buf.Settings["softwrap"].(bool) {
|
||||
for _, c := range w.Buf.GetCursors() {
|
||||
c.LastVisualX = c.GetVisualX()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetActive marks the window as active.
|
||||
@@ -150,10 +147,18 @@ func (w *BufWindow) updateDisplayInfo() {
|
||||
w.gutterOffset += w.maxLineNumLength + 1
|
||||
}
|
||||
|
||||
prevBufWidth := w.bufWidth
|
||||
|
||||
w.bufWidth = w.Width - w.gutterOffset
|
||||
if w.Buf.Settings["scrollbar"].(bool) && w.Buf.LinesNum() > w.Height {
|
||||
w.bufWidth--
|
||||
}
|
||||
|
||||
if w.bufWidth != prevBufWidth && w.Buf.Settings["softwrap"].(bool) {
|
||||
for _, c := range w.Buf.GetCursors() {
|
||||
c.LastVisualX = c.GetVisualX()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *BufWindow) getStartInfo(n, lineN int) ([]byte, int, int, *tcell.Style) {
|
||||
@@ -219,7 +224,7 @@ func (w *BufWindow) Relocate() bool {
|
||||
w.StartLine = c
|
||||
ret = true
|
||||
}
|
||||
if c.GreaterThan(w.Scroll(w.StartLine, height-1-scrollmargin)) && c.LessThan(w.Scroll(bEnd, -scrollmargin+1)) {
|
||||
if c.GreaterThan(w.Scroll(w.StartLine, height-1-scrollmargin)) && c.LessEqual(w.Scroll(bEnd, -scrollmargin)) {
|
||||
w.StartLine = w.Scroll(c, -height+1+scrollmargin)
|
||||
ret = true
|
||||
} else if c.GreaterThan(w.Scroll(bEnd, -scrollmargin)) && c.GreaterThan(w.Scroll(w.StartLine, height-1)) {
|
||||
@@ -620,6 +625,11 @@ func (w *BufWindow) displayBuffer() {
|
||||
width = util.Min(ts, maxWidth-vloc.X)
|
||||
totalwidth += ts
|
||||
default:
|
||||
if unicode.IsUpper(r) {
|
||||
width = 2
|
||||
totalwidth += 2
|
||||
break
|
||||
}
|
||||
width = runewidth.RuneWidth(r)
|
||||
totalwidth += width
|
||||
}
|
||||
@@ -654,6 +664,13 @@ func (w *BufWindow) displayBuffer() {
|
||||
}
|
||||
|
||||
for _, r := range word {
|
||||
if unicode.IsUpper(r.r) {
|
||||
draw('~', nil, r.style, true, true)
|
||||
draw(r.r, r.combc, r.style, true, false)
|
||||
bloc.X++
|
||||
continue
|
||||
}
|
||||
|
||||
draw(r.r, r.combc, r.style, true, true)
|
||||
|
||||
// Draw any extra characters either spaces for tabs or @ for incomplete wide runes
|
||||
|
||||
@@ -30,6 +30,28 @@ func (s SLoc) GreaterThan(b SLoc) bool {
|
||||
return s.Line == b.Line && s.Row > b.Row
|
||||
}
|
||||
|
||||
// LessEqual returns true if s is less than or equal to b
|
||||
func (s SLoc) LessEqual(b SLoc) bool {
|
||||
if s.Line < b.Line {
|
||||
return true
|
||||
}
|
||||
if s.Line == b.Line && s.Row < b.Row {
|
||||
return true
|
||||
}
|
||||
return s == b
|
||||
}
|
||||
|
||||
// GreaterEqual returns true if s is bigger than or equal to b
|
||||
func (s SLoc) GreaterEqual(b SLoc) bool {
|
||||
if s.Line > b.Line {
|
||||
return true
|
||||
}
|
||||
if s.Line == b.Line && s.Row > b.Row {
|
||||
return true
|
||||
}
|
||||
return s == b
|
||||
}
|
||||
|
||||
// VLoc represents a location in the buffer as a visual location in the
|
||||
// linewrapped buffer.
|
||||
type VLoc struct {
|
||||
|
||||
@@ -79,6 +79,10 @@ func ShowFakeCursor(x, y int) {
|
||||
lastCursor.style = style
|
||||
}
|
||||
|
||||
func UseFake() bool {
|
||||
return util.FakeCursor || config.GetGlobalOption("fakecursor").(bool)
|
||||
}
|
||||
|
||||
// ShowFakeCursorMulti is the same as ShowFakeCursor except it does not
|
||||
// reset previous locations of the cursor
|
||||
// Fake cursors are also necessary to display multiple cursors
|
||||
@@ -91,7 +95,7 @@ func ShowFakeCursorMulti(x, y int) {
|
||||
// if enabled or using the terminal cursor otherwise
|
||||
// By default only the windows console will use a fake cursor
|
||||
func ShowCursor(x, y int) {
|
||||
if util.FakeCursor {
|
||||
if UseFake() {
|
||||
ShowFakeCursor(x, y)
|
||||
} else {
|
||||
Screen.ShowCursor(x, y)
|
||||
@@ -106,7 +110,7 @@ func SetContent(x, y int, mainc rune, combc []rune, style tcell.Style) {
|
||||
}
|
||||
|
||||
Screen.SetContent(x, y, mainc, combc, style)
|
||||
if util.FakeCursor && lastCursor.x == x && lastCursor.y == y {
|
||||
if UseFake() && lastCursor.x == x && lastCursor.y == y {
|
||||
lastCursor.r = mainc
|
||||
lastCursor.style = style
|
||||
lastCursor.combc = combc
|
||||
|
||||
@@ -128,7 +128,13 @@ func (t *Terminal) Close() {
|
||||
// call the lua function that the user has given as a callback
|
||||
if t.getOutput {
|
||||
if t.callback != nil {
|
||||
t.callback(t.output.String())
|
||||
Jobs <- JobFunction{
|
||||
Function: func(out string, args []interface{}) {
|
||||
t.callback(out)
|
||||
},
|
||||
Output: t.output.String(),
|
||||
Args: nil,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
@@ -493,3 +494,16 @@ func Unzip(src, dest string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HttpRequest returns a new http.Client for making custom requests (for lua plugins)
|
||||
func HttpRequest(method string, url string, headers []string) (resp *http.Response, err error) {
|
||||
client := http.Client{}
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(headers); i += 2 {
|
||||
req.Header.Add(headers[i], headers[i+1])
|
||||
}
|
||||
return client.Do(req)
|
||||
}
|
||||
|
||||
@@ -52,6 +52,10 @@ can change it!
|
||||
| Ctrl-n | Find next instance of current search |
|
||||
| Ctrl-p | Find previous instance of current search |
|
||||
|
||||
Note: Ctrl-n and Ctrl-p should be used from the main buffer, not from inside
|
||||
the search prompt. After Ctrl-f, press enter to complete the search and then
|
||||
you can use Ctrl-n and Ctrl-p to cycle through matches.
|
||||
|
||||
### File Operations
|
||||
|
||||
| Key | Description of function |
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
# Micro help text
|
||||
|
||||
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.
|
||||
Micro is an easy to use, intuitive, text editor that takes advantage of the
|
||||
full capabilities of modern terminals.
|
||||
|
||||
To open the command bar, press Ctrl-e. This enables a `>` prompt for typing
|
||||
commands. From now on when the documentation says to run a command such as `>
|
||||
help`, this means press Ctrl-e and type `help` (and press enter to execute the
|
||||
command).
|
||||
Micro can be controlled by commands entered on the command bar, or with
|
||||
keybindings. To open the command bar, press Ctrl-e: the `>` prompt will
|
||||
display. From now on, when the documentation shows a command to run (such as
|
||||
`> help`), press Ctrl-e and type the command followed by enter.
|
||||
|
||||
For a list of the default keybindings run `> help defaultkeys`.
|
||||
For more information on keybindings see `> help keybindings`.
|
||||
For a list of the default keybindings, run `> help defaultkeys`.
|
||||
For more information on keybindings, see `> help keybindings`.
|
||||
To toggle a short list of important keybindings, press Alt-g.
|
||||
|
||||
## Quick-start
|
||||
|
||||
Press Ctrl-q to quit, and Ctrl-s to save. Press Ctrl-e to start typing commands
|
||||
and you can see which commands are available by pressing tab, or by viewing the
|
||||
help topic `> help commands`.
|
||||
To quit, press Ctrl-q. Save by pressing Ctrl-s. Press Ctrl-e, as previously
|
||||
mentioned, to start typing commands. To see which commands are available, at the
|
||||
prompt, press tab, or view the help topic with `> help commands`.
|
||||
|
||||
Move the cursor around with the mouse or the arrow keys. Run
|
||||
`> help defaultkeys` to get a quick, easy overview of the default hotkeys and
|
||||
what they do. For more info on rebinding keys, see type `> help keybindings`.
|
||||
Move the cursor around with the mouse or with the arrow keys. Enter text simply
|
||||
by pressing character keys.
|
||||
|
||||
If the colorscheme doesn't look good, you can change it with
|
||||
`> set colorscheme ...`. You can press tab to see the available colorschemes,
|
||||
@@ -32,19 +31,20 @@ Press Ctrl-w to move between splits, and type `> vsplit filename` or
|
||||
|
||||
## Accessing more help
|
||||
|
||||
Micro has a built-in help system which can be accessed with the `help` command.
|
||||
Micro has a built-in help system which can be accessed with the `> help` command.
|
||||
|
||||
To use it, press Ctrl-e to access command mode and type in `help` followed by a
|
||||
topic. Typing `help` followed by nothing will open this page.
|
||||
To view help for the various available topics, press Ctrl-e to access command
|
||||
mode and type in `> help` followed by a topic. Typing just `> help` will open
|
||||
this page.
|
||||
|
||||
Here are the possible help topics that you can read:
|
||||
Here are the available help topics:
|
||||
|
||||
* tutorial: A brief tutorial which gives an overview of all the other help
|
||||
topics
|
||||
* keybindings: Gives a full list of the default keybindings as well as how to
|
||||
rebind them
|
||||
* defaultkeys: Gives a more straight-forward list of the hotkey commands and
|
||||
what they do.
|
||||
what they do
|
||||
* commands: Gives a list of all the commands and what they do
|
||||
* options: Gives a list of all the options you can customize
|
||||
* plugins: Explains how micro's plugin system works and how to create your own
|
||||
|
||||
@@ -470,6 +470,7 @@ conventions for text editing defaults.
|
||||
"Ctrl-o": "OpenFile",
|
||||
"Ctrl-s": "Save",
|
||||
"Ctrl-f": "Find",
|
||||
"Alt-F": "FindLiteral",
|
||||
"Ctrl-n": "FindNext",
|
||||
"Ctrl-p": "FindPrevious",
|
||||
"Ctrl-z": "Undo",
|
||||
|
||||
@@ -223,6 +223,15 @@ Here are the available options:
|
||||
|
||||
default value: `true`
|
||||
|
||||
* `multiopen`: specifies how to layout multiple files opened at startup.
|
||||
Most useful as a command-line option, like `-multiopen vsplit`. Possible
|
||||
values correspond to commands (see `> help commands`) that open files:
|
||||
* `tab`: open each file in a separate tab.
|
||||
* `vsplit`: open files side-by-side.
|
||||
* `hsplit`: open files stacked top to bottom.
|
||||
|
||||
default value: `tab`
|
||||
|
||||
* `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
|
||||
@@ -462,7 +471,7 @@ so that you can see what the formatting should look like.
|
||||
"filetype": "unknown",
|
||||
"incsearch": true,
|
||||
"ftoptions": true,
|
||||
"ignorecase": false,
|
||||
"ignorecase": true,
|
||||
"indentchar": " ",
|
||||
"infobar": true,
|
||||
"initlua": true,
|
||||
|
||||
@@ -287,6 +287,7 @@ The packages and functions are listed below (in Go type signatures):
|
||||
- `String(b []byte) string`: converts a byte array to a string.
|
||||
- `RuneStr(r rune) string`: converts a rune to a string.
|
||||
- `Unzip(src, dest string) error`: unzips a file to given folder.
|
||||
- `HttpRequest(method string, url string, headers []string) (http.Response, error)`: makes a http request.
|
||||
|
||||
This may seem like a small list of available functions but some of the objects
|
||||
returned by the functions have many methods. The Lua plugin may access any
|
||||
|
||||
@@ -60,23 +60,30 @@ ft["zig"] = "// %s"
|
||||
ft["zscript"] = "// %s"
|
||||
ft["zsh"] = "# %s"
|
||||
|
||||
local last_ft
|
||||
|
||||
function updateCommentType(buf)
|
||||
if ft[buf.Settings["filetype"]] ~= nil and ft[buf.Settings["filetype"]] ~= nil then
|
||||
buf.Settings["commenttype"] = ft[buf.Settings["filetype"]]
|
||||
elseif buf.Settings["commenttype"] == nil then
|
||||
buf.Settings["commenttype"] = "# %s"
|
||||
if buf.Settings["commenttype"] == nil or last_ft ~= buf.Settings["filetype"] then
|
||||
if ft[buf.Settings["filetype"]] ~= nil then
|
||||
buf.Settings["commenttype"] = ft[buf.Settings["filetype"]]
|
||||
else
|
||||
buf.Settings["commenttype"] = "# %s"
|
||||
end
|
||||
|
||||
last_ft = buf.Settings["filetype"]
|
||||
end
|
||||
end
|
||||
|
||||
function isCommented(bp, lineN, commentRegex)
|
||||
local line = bp.Buf:Line(lineN)
|
||||
if string.match(line, commentRegex) then
|
||||
local regex = commentRegex:gsub("%s+", "%s*")
|
||||
if string.match(line, regex) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function commentLine(bp, lineN)
|
||||
function commentLine(bp, lineN, indentLen)
|
||||
updateCommentType(bp.Buf)
|
||||
|
||||
local line = bp.Buf:Line(lineN)
|
||||
@@ -84,8 +91,11 @@ function commentLine(bp, lineN)
|
||||
local sel = -bp.Cursor.CurSelection
|
||||
local curpos = -bp.Cursor.Loc
|
||||
local index = string.find(commentType, "%%s") - 1
|
||||
local commentedLine = commentType:gsub("%%s", trim(line))
|
||||
bp.Buf:Replace(buffer.Loc(0, lineN), buffer.Loc(#line, lineN), util.GetLeadingWhitespace(line) .. commentedLine)
|
||||
local indent = string.sub(line, 1, indentLen)
|
||||
local trimmedLine = string.sub(line, indentLen + 1)
|
||||
trimmedLine = trimmedLine:gsub("%%", "%%%%")
|
||||
local commentedLine = commentType:gsub("%%s", trimmedLine)
|
||||
bp.Buf:Replace(buffer.Loc(0, lineN), buffer.Loc(#line, lineN), indent .. commentedLine)
|
||||
if bp.Cursor:HasSelection() then
|
||||
bp.Cursor.CurSelection[1].Y = sel[1].Y
|
||||
bp.Cursor.CurSelection[2].Y = sel[2].Y
|
||||
@@ -107,6 +117,9 @@ function uncommentLine(bp, lineN, commentRegex)
|
||||
local sel = -bp.Cursor.CurSelection
|
||||
local curpos = -bp.Cursor.Loc
|
||||
local index = string.find(commentType, "%%s") - 1
|
||||
if not string.match(line, commentRegex) then
|
||||
commentRegex = commentRegex:gsub("%s+", "%s*")
|
||||
end
|
||||
if string.match(line, commentRegex) then
|
||||
uncommentedLine = string.match(line, commentRegex)
|
||||
bp.Buf:Replace(buffer.Loc(0, lineN), buffer.Loc(#line, lineN), util.GetLeadingWhitespace(line) .. uncommentedLine)
|
||||
@@ -128,7 +141,7 @@ function toggleCommentLine(bp, lineN, commentRegex)
|
||||
if isCommented(bp, lineN, commentRegex) then
|
||||
uncommentLine(bp, lineN, commentRegex)
|
||||
else
|
||||
commentLine(bp, lineN)
|
||||
commentLine(bp, lineN, #util.GetLeadingWhitespace(bp.Buf:Line(lineN)))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -141,11 +154,22 @@ function toggleCommentSelection(bp, startLine, endLine, commentRegex)
|
||||
end
|
||||
end
|
||||
|
||||
-- NOTE: we assume that the indentation is either tabs only or spaces only
|
||||
local indentMin = -1
|
||||
if not allComments then
|
||||
for line = startLine, endLine do
|
||||
local indentLen = #util.GetLeadingWhitespace(bp.Buf:Line(line))
|
||||
if indentMin == -1 or indentLen < indentMin then
|
||||
indentMin = indentLen
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for line = startLine, endLine do
|
||||
if allComments then
|
||||
uncommentLine(bp, line, commentRegex)
|
||||
else
|
||||
commentLine(bp, line)
|
||||
commentLine(bp, line, indentMin)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -154,7 +178,7 @@ function comment(bp, args)
|
||||
updateCommentType(bp.Buf)
|
||||
|
||||
local commentType = bp.Buf.Settings["commenttype"]
|
||||
local commentRegex = "^%s*" .. commentType:gsub("%%","%%%%"):gsub("%$","%$"):gsub("%)","%)"):gsub("%(","%("):gsub("%?","%?"):gsub("%*", "%*"):gsub("%-", "%-"):gsub("%.", "%."):gsub("%+", "%+"):gsub("%]", "%]"):gsub("%[", "%["):gsub("%%%%s", "(.*)"):gsub("%s+", "%s*")
|
||||
local commentRegex = "^%s*" .. commentType:gsub("%%","%%%%"):gsub("%$","%$"):gsub("%)","%)"):gsub("%(","%("):gsub("%?","%?"):gsub("%*", "%*"):gsub("%-", "%-"):gsub("%.", "%."):gsub("%+", "%+"):gsub("%]", "%]"):gsub("%[", "%["):gsub("%%%%s", "(.*)")
|
||||
|
||||
if bp.Cursor:HasSelection() then
|
||||
if bp.Cursor.CurSelection[1]:GreaterThan(-bp.Cursor.CurSelection[2]) then
|
||||
@@ -175,11 +199,6 @@ function comment(bp, args)
|
||||
end
|
||||
end
|
||||
|
||||
function trim(s)
|
||||
local trimmed = s:gsub("^%s*(.-)%s*$", "%1"):gsub("%%","%%%%")
|
||||
return trimmed
|
||||
end
|
||||
|
||||
function string.starts(String,Start)
|
||||
return string.sub(String,1,string.len(Start))==Start
|
||||
end
|
||||
|
||||
@@ -9,7 +9,7 @@ rules:
|
||||
- type: "\\b((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\\b"
|
||||
- type: "\\b[a-z_][0-9a-z_]+(_t|_T)\\b"
|
||||
- type.extended: "\\b(bool)\\b"
|
||||
- statement: "\\b(volatile|register)\\b"
|
||||
- statement: "\\b(volatile|register|restrict)\\b"
|
||||
- statement: "\\b(for|if|while|do|else|case|default|switch)\\b"
|
||||
- statement: "\\b(goto|continue|break|return)\\b"
|
||||
- preproc: "^[[:space:]]*#[[:space:]]*(define|pragma|include|(un|ifn?)def|endif|el(if|se)|if|warning|error)"
|
||||
@@ -20,7 +20,7 @@ rules:
|
||||
- symbol.operator: "([.:;,+*|=!\\%]|<|>|/|-|&)"
|
||||
- symbol.brackets: "[(){}]|\\[|\\]"
|
||||
# Integer Constants
|
||||
- constant.number: "(\\b([1-9][0-9]*|0[0-7]*|0[Xx][0-9A-Fa-f]+|0[Bb][01]+)([Uu]?[Ll][Ll]?|[Ll][Ll]?[Uu]?)?\\b)"
|
||||
- constant.number: "(\\b([1-9][0-9]*|0[0-7]*|0[Xx][0-9A-Fa-f]+|0[Bb][01]+)([Uu][Ll]?[Ll]?|[Ll][Ll]?[Uu]?)?\\b)"
|
||||
# Decimal Floating Constants
|
||||
- constant.number: "(\\b(([0-9]*[.][0-9]+|[0-9]+[.][0-9]*)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)[FfLl]?\\b)"
|
||||
# Hexadecimal Floating Constants
|
||||
|
||||
68
runtime/syntax/cuda.yaml
Normal file
68
runtime/syntax/cuda.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
filetype: cuda
|
||||
|
||||
detect:
|
||||
filename: "(\\.cu[h]?$)"
|
||||
|
||||
rules:
|
||||
- identifier: "\\b[A-Z_][0-9A-Z_]*\\b"
|
||||
- type: "\\b(float|double|bool|char|int|short|long|enum|void|struct|union|typedef|(un)?signed|inline)\\b"
|
||||
- type: "\\b(((s?size)|((u_?)?int(8|16|32|64|ptr))|char(8|16|32))_t|wchar_t)\\b"
|
||||
- type: "\\b[a-z_][0-9a-z_]+(_t|_T)\\b"
|
||||
- type: "\\b(final|override)\\b"
|
||||
- type.keyword: "\\b(auto|volatile|const(expr|eval|init)?|mutable|register|thread_local|static|extern|decltype|explicit|virtual)\\b"
|
||||
- statement: "\\b(class|namespace|template|typename|this|friend|using|public|protected|private|noexcept)\\b"
|
||||
- statement: "\\b(concept|requires)\\b"
|
||||
- statement: "\\b(import|export|module)\\b"
|
||||
- statement: "\\b(for|if|while|do|else|case|default|switch)\\b"
|
||||
- statement: "\\b(try|throw|catch|operator|new|delete|static_assert)\\b"
|
||||
- statement: "\\b(goto|continue|break|return)\\b"
|
||||
- preproc: "^[[:space:]]*#[[:space:]]*(define|pragma|include|(un|ifn?)def|endif|el(if|se)|if|warning|error)|_Pragma"
|
||||
|
||||
# Conditionally-supported/extension keywords
|
||||
- statement: "\\b(asm|fortran)\\b"
|
||||
|
||||
# GCC builtins
|
||||
- statement: "(__attribute__[[:space:]]*\\(\\([^)]*\\)\\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__)"
|
||||
|
||||
# CUDA specific keywords
|
||||
- statement: "__(global|device|host|shared)__"
|
||||
|
||||
# Operator Color
|
||||
- symbol.operator: "[-+*/%=<>.:;,~&|^!?]|\\b(sizeof|alignof|typeid|(and|or|xor|not)(_eq)?|bitor|compl|bitand|(const|dynamic|reinterpret|static)_cast)\\b"
|
||||
# Parenthetical Color
|
||||
- symbol.brackets: "[(){}]|\\[|\\]"
|
||||
# Integer Literals
|
||||
- constant.number: "(\\b([1-9][0-9']*|0[0-7']*|0[Xx][0-9a-fA-F']+|0[Bb][01]+)([Uu]?[Ll][Ll]?|[Ll][Ll]?[Uu]?)?\\b)"
|
||||
# Decimal Floating-point Literals
|
||||
- constant.number: "(\\b(([0-9']*[.][0-9']+|[0-9']+[.][0-9']*)([Ee][+-]?[0-9']+)?|[0-9']+[Ee][+-]?[0-9']+)[FfLl]?\\b)"
|
||||
# Hexadecimal Floating-point Literals
|
||||
- constant.number: "(\\b0[Xx]([0-9a-zA-Z']*[.][0-9a-zA-Z']+|[0-9a-zA-Z']+[.][0-9a-zA-Z']*)[Pp][+-]?[0-9']+[FfLl]?\\b)"
|
||||
- constant.bool: "(\\b(true|false|NULL|nullptr)\\b)"
|
||||
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\([\"'abfnrtv\\\\]|[0-3]?[0-7]{1,2}|x[0-9A-Fa-f]{1,2}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})"
|
||||
|
||||
- constant.string:
|
||||
start: "'"
|
||||
end: "'"
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- error: "..+"
|
||||
- constant.specialChar: "\\\\([\"'abfnrtv\\\\]|[0-3]?[0-7]{1,2}|x[0-9A-Fa-f]{1,2}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})"
|
||||
|
||||
- comment:
|
||||
start: "//"
|
||||
end: "$"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
|
||||
- comment:
|
||||
start: "/\\*"
|
||||
end: "\\*/"
|
||||
rules:
|
||||
- todo: "(TODO|XXX|FIXME):?"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
filetype: git-commit
|
||||
|
||||
detect:
|
||||
filename: "^(.*[\\/])?(COMMIT_EDITMSG|TAG_EDITMSG|MERGE_MSG|git-rebase-todo)$"
|
||||
filename: "^(.*[\\/])?(COMMIT_EDITMSG|TAG_EDITMSG|MERGE_MSG)$"
|
||||
|
||||
rules:
|
||||
# File changes
|
||||
|
||||
@@ -39,13 +39,12 @@ rules:
|
||||
rules:
|
||||
- constant.specialChar: "\\\\([\"'abfnrtv\\\\]|[0-3]?[0-7]{1,2}|x[0-9A-Fa-f]{1,2}|u[0-9A-Fa-f]{1,4}|U[0-9A-Fa-f]{1,8})"
|
||||
|
||||
# Lifted from Rust's syntax highlighting
|
||||
- constant.string: "'(\\\\.|.)'"
|
||||
- constant.string:
|
||||
start: "'"
|
||||
start: "'\""
|
||||
end: "'"
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- error: "..+"
|
||||
- constant.specialChar: "\\\\([\"'abfnrtv\\\\]|[0-3]?[0-7]{1,2}|x[0-9A-Fa-f]{1,2}|u[0-9A-Fa-f]{1,4}|U[0-9A-Fa-f]{1,8})"
|
||||
rules: []
|
||||
|
||||
- comment:
|
||||
start: "#="
|
||||
|
||||
40
runtime/syntax/justfile.yaml
Normal file
40
runtime/syntax/justfile.yaml
Normal file
@@ -0,0 +1,40 @@
|
||||
# For more information, see https://github.com/casey/just
|
||||
filetype: 'justfile'
|
||||
|
||||
detect:
|
||||
filename: '(^\\.?[Jj]ustfile|\\.just)$'
|
||||
header: "^#!.*/(env +)?[bg]?just --justfile"
|
||||
|
||||
rules:
|
||||
- preproc: "\\<(ifeq|ifdef|ifneq|ifndef|else|endif)\\>"
|
||||
- statement: "^(export|include|override)\\>"
|
||||
- symbol.operator: "^[^:= ]+:"
|
||||
- symbol.operator: "([=,%]|\\+=|\\?=|:=|&&|\\|\\|)"
|
||||
- statement: "\\$\\((abspath|addprefix|addsuffix|and|basename|call|dir)[[:space:]]"
|
||||
- statement: "\\$\\((error|eval|filter|filter-out|findstring|firstword)[[:space:]]"
|
||||
- statement: "\\$\\((flavor|foreach|if|info|join|lastword|notdir|or)[[:space:]]"
|
||||
- statement: "\\$\\((origin|patsubst|realpath|shell|sort|strip|suffix)[[:space:]]"
|
||||
- statement: "\\$\\((value|warning|wildcard|word|wordlist|words)[[:space:]]"
|
||||
# default functions - probably shouldn't be overwritten by assignment
|
||||
- statement: "\\b(arch|os|os_family|env_var|invocation_directory|justfile|justfile_directory|just_executable|lowercase|quote|replace|trim|trim_end|trim_end|trim_end_match|trim_end_matches|trim_start|trim_start_match|trim_start_matches|uppercase)\\b"
|
||||
- identifier: "^.+:"
|
||||
- identifier: "[()$]"
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
- constant.string:
|
||||
start: "'"
|
||||
end: "'"
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
- identifier: "\\$+(\\{[^} ]+\\}|\\([^) ]+\\))"
|
||||
- identifier: "\\$[@^<*?%|+]|\\$\\([@^<*?%+-][DF]\\)"
|
||||
- identifier: "\\$\\$|\\\\.?"
|
||||
- comment:
|
||||
start: "#"
|
||||
end: "$"
|
||||
rules: []
|
||||
@@ -1,7 +1,7 @@
|
||||
filetype: perl
|
||||
|
||||
detect:
|
||||
filename: "\\.pp[lmp]$"
|
||||
filename: "\\.p[lmp]$"
|
||||
header: "^#!.*/(env +)?perl( |$)"
|
||||
|
||||
rules:
|
||||
|
||||
55
runtime/syntax/smalltalk.yaml
Normal file
55
runtime/syntax/smalltalk.yaml
Normal file
@@ -0,0 +1,55 @@
|
||||
filetype: smalltalk
|
||||
|
||||
detect:
|
||||
filename: "\\.(st|sources|changes)$"
|
||||
|
||||
rules:
|
||||
- statement: "\\b(self|nil|true|false|ifTrue|ifFalse|whileTrue|whileFalse)\\b"
|
||||
- constant: "(\\$|@|@@)?\\b[A-Z]+[0-9A-Z_a-z]*"
|
||||
- constant.number: "(?i)\\b0x[0-9a-fA-F][0-9a-f_]*\\b"
|
||||
- constant.number: "(?i)\\b0b[01][01_]*\\b"
|
||||
- constant.number: "(?i)\\b[0-9][0-9_]*(['.'][0-9_]+)?(e[\\-]?[0-9_]+)?\\b"
|
||||
# Ruby "Symbols"
|
||||
- constant: "(i?)([ ]|^):[0-9A-Z_]+\\b"
|
||||
- constant: "\\b(__FILE__|__LINE__)\\b"
|
||||
- constant: "/([^/]|(\\\\/))*/[iomx]*|%r\\{([^}]|(\\\\}))*\\}[iomx]*"
|
||||
|
||||
- constant.string:
|
||||
start: "'"
|
||||
end: "'"
|
||||
skip: "\\\\."
|
||||
rules: []
|
||||
|
||||
- constant.string:
|
||||
start: "\""
|
||||
end: "\""
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- symbol.brackets:
|
||||
start: "#\\{"
|
||||
end: "\\}"
|
||||
rules:
|
||||
- default: ".*"
|
||||
|
||||
- constant.string.exec:
|
||||
start: "`"
|
||||
end: "`"
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- symbol.brackets:
|
||||
start: "#\\{"
|
||||
end: "\\}"
|
||||
rules:
|
||||
- default: ".*"
|
||||
|
||||
- constant.string: "%[QW]?\\{[^}]*\\}|%[QW]?\\([^)]*\\)|%[QW]?<[^>]*>|%[QW]?\\[[^]]*\\]|%[QW]?\\$[^$]*\\$|%[QW]?\\^[^^]*\\^|%[QW]?![^!]*!"
|
||||
- constant.string: "%[qw]\\{[^}]*\\}|%[qw]\\([^)]*\\)|%[qw]<[^>]*>|%[qw]\\[[^]]*\\]|%[qw]\\$[^$]*\\$|%[qw]\\^[^^]*\\^|%[qw]![^!]*!"
|
||||
- constant.string.exec: "%[x]\\{[^}]*\\}|%[x]\\([^)]*\\)|%[x]<[^>]*>|%[x]\\[[^]]*\\]|%[x]\\$[^$]*\\$|%[x]\\^[^^]*\\^|%[x]![^!]*!"
|
||||
- symbol.operator: "[-+/*=<>!~%&|^]|\\b:"
|
||||
- symbol.brackets: "([(){}]|\\[|\\])"
|
||||
- constant.macro:
|
||||
start: "<<-?'?EOT'?"
|
||||
end: "^EOT"
|
||||
rules: []
|
||||
|
||||
- preproc.shebang: "^#!.+?( |$)"
|
||||
@@ -41,4 +41,9 @@ rules:
|
||||
skip: "\\\\."
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
|
||||
- constant.string:
|
||||
start: "`"
|
||||
end: "`"
|
||||
rules:
|
||||
- constant.specialChar: "\\\\."
|
||||
- identifier: "\\x24\\{.*?\\}"
|
||||
|
||||
@@ -22,6 +22,13 @@ mv micro micro-$1
|
||||
tar -czf micro-$1-osx.tar.gz micro-$1
|
||||
mv micro-$1-osx.tar.gz binaries
|
||||
|
||||
# Mac ARM64
|
||||
echo "MacOS ARM64"
|
||||
GOOS=darwin GOARCH=arm64 make build
|
||||
mv micro micro-$1
|
||||
tar -czf micro-$1-macos-arm64.tar.gz micro-$1
|
||||
mv micro-$1-macos-arm64.tar.gz binaries
|
||||
|
||||
# Linux
|
||||
echo "Linux 64"
|
||||
GOOS=linux GOARCH=amd64 make build
|
||||
|
||||
@@ -17,6 +17,7 @@ hub release edit nightly \
|
||||
--draft=false \
|
||||
--message "$MESSAGE (please DISREGARD the creation date of this Github release). Assets uploaded on $(date) for commit $commitID." \
|
||||
--attach "binaries/micro-$1-osx.tar.gz" \
|
||||
--attach "binaries/micro-$1-macos-arm64.tar.gz" \
|
||||
--attach "binaries/micro-$1-linux64.tar.gz" \
|
||||
--attach "binaries/micro-$1-linux64-static.tar.gz" \
|
||||
--attach "binaries/micro-$1-amd64.deb" \
|
||||
|
||||
@@ -21,6 +21,7 @@ hub release create $tag \
|
||||
--prerelease \
|
||||
--message "$1${NL}${NL}$2" \
|
||||
--attach "binaries/micro-$1-osx.tar.gz" \
|
||||
--attach "binaries/micro-$1-macos-arm64.tar.gz" \
|
||||
--attach "binaries/micro-$1-linux64.tar.gz" \
|
||||
--attach "binaries/micro-$1-linux64-static.tar.gz" \
|
||||
--attach "binaries/micro-$1-amd64.deb" \
|
||||
|
||||
@@ -20,6 +20,7 @@ echo "Creating new release"
|
||||
hub release create $tag \
|
||||
--message "$1${NL}${NL}$2" \
|
||||
--attach "binaries/micro-$1-osx.tar.gz" \
|
||||
--attach "binaries/micro-$1-macos-arm64.tar.gz" \
|
||||
--attach "binaries/micro-$1-linux64.tar.gz" \
|
||||
--attach "binaries/micro-$1-linux64-static.tar.gz" \
|
||||
--attach "binaries/micro-$1-amd64.deb" \
|
||||
|
||||
Reference in New Issue
Block a user