提交 86df9ad3 编写于 作者: Z Zachary Yedidia

Merge

......@@ -118,6 +118,9 @@ func luaImportMicroBuffer() *lua.LTable {
ulua.L.SetField(pkg, "Loc", luar.New(ulua.L, func(x, y int) buffer.Loc {
return buffer.Loc{x, y}
}))
ulua.L.SetField(pkg, "SLoc", luar.New(ulua.L, func(line, row int) display.SLoc {
return display.SLoc{line, row}
}))
ulua.L.SetField(pkg, "BTDefault", luar.New(ulua.L, buffer.BTDefault.Kind))
ulua.L.SetField(pkg, "BTHelp", luar.New(ulua.L, buffer.BTHelp.Kind))
ulua.L.SetField(pkg, "BTLog", luar.New(ulua.L, buffer.BTLog.Kind))
......
......@@ -27,6 +27,6 @@ require (
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
replace github.com/mattn/go-runewidth => github.com/zyedidia/go-runewidth v0.0.12
go 1.11
......@@ -27,6 +27,8 @@ github.com/p-e-w/go-runewidth v0.0.10-0.20200613030200-3e1705c5c059 h1:/+h2b6i15
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/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
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=
......@@ -44,6 +46,8 @@ github.com/zyedidia/clipboard v1.0.3 h1:F/nCDVYMdbDWTmY8s8cJl0tnwX32q96IF09JHM14
github.com/zyedidia/clipboard v1.0.3/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-runewidth v0.0.12 h1:aHWj8qL3aH7caRzoPBJXe1pEaZBXHpKtfTuiBo5p74Q=
github.com/zyedidia/go-runewidth v0.0.12/go.mod h1:vF8djYdLmG8BJaUZ4CznFYCJ3pFR8m4B4VinTvTTarU=
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=
......
......@@ -10,6 +10,7 @@ import (
"github.com/zyedidia/micro/v2/internal/buffer"
"github.com/zyedidia/micro/v2/internal/clipboard"
"github.com/zyedidia/micro/v2/internal/config"
"github.com/zyedidia/micro/v2/internal/display"
"github.com/zyedidia/micro/v2/internal/screen"
"github.com/zyedidia/micro/v2/internal/shell"
"github.com/zyedidia/micro/v2/internal/util"
......@@ -19,21 +20,26 @@ import (
// ScrollUp is not an action
func (h *BufPane) ScrollUp(n int) {
v := h.GetView()
if v.StartLine >= n {
v.StartLine -= n
h.SetView(v)
} else {
v.StartLine = 0
}
v.StartLine = h.Scroll(v.StartLine, -n)
h.SetView(v)
}
// ScrollDown is not an action
func (h *BufPane) ScrollDown(n int) {
v := h.GetView()
if v.StartLine <= h.Buf.LinesNum()-1-n {
v.StartLine += n
h.SetView(v)
v.StartLine = h.Scroll(v.StartLine, n)
h.SetView(v)
}
// If the user has scrolled past the last line, ScrollAdjust can be used
// to shift the view so that the last line is at the bottom
func (h *BufPane) ScrollAdjust() {
v := h.GetView()
end := h.SLocFromLoc(h.Buf.End())
if h.Diff(v.StartLine, end) < v.Height-1 {
v.StartLine = h.Scroll(end, -v.Height+1)
}
h.SetView(v)
}
// MousePress is the event that should happen when a normal click happens
......@@ -111,15 +117,9 @@ func (h *BufPane) ScrollDownAction() bool {
// Center centers the view on the cursor
func (h *BufPane) Center() bool {
v := h.GetView()
v.StartLine = h.Cursor.Y - v.Height/2
if v.StartLine+v.Height > h.Buf.LinesNum() {
v.StartLine = h.Buf.LinesNum() - v.Height
}
if v.StartLine < 0 {
v.StartLine = 0
}
v.StartLine = h.Scroll(h.SLocFromLoc(h.Cursor.Loc), -v.Height/2)
h.SetView(v)
h.Relocate()
h.ScrollAdjust()
return true
}
......@@ -1243,45 +1243,31 @@ func (h *BufPane) JumpLine() bool {
// Start moves the viewport to the start of the buffer
func (h *BufPane) Start() bool {
v := h.GetView()
v.StartLine = 0
v.StartLine = display.SLoc{0, 0}
h.SetView(v)
return true
}
// End moves the viewport to the end of the buffer
func (h *BufPane) End() bool {
// TODO: softwrap problems?
v := h.GetView()
if v.Height > h.Buf.LinesNum() {
v.StartLine = 0
h.SetView(v)
} else {
v.StartLine = h.Buf.LinesNum() - v.Height
h.SetView(v)
}
v.StartLine = h.Scroll(h.SLocFromLoc(h.Buf.End()), -v.Height+1)
h.SetView(v)
return true
}
// PageUp scrolls the view up a page
func (h *BufPane) PageUp() bool {
v := h.GetView()
if v.StartLine > v.Height {
h.ScrollUp(v.Height)
} else {
v.StartLine = 0
}
h.SetView(v)
h.ScrollUp(v.Height)
return true
}
// PageDown scrolls the view down a page
func (h *BufPane) PageDown() bool {
v := h.GetView()
if h.Buf.LinesNum()-(v.StartLine+v.Height) > v.Height {
h.ScrollDown(v.Height)
} else if h.Buf.LinesNum() >= v.Height {
v.StartLine = h.Buf.LinesNum() - v.Height
}
h.ScrollDown(v.Height)
h.ScrollAdjust()
return true
}
......@@ -1338,24 +1324,15 @@ func (h *BufPane) CursorPageDown() bool {
// HalfPageUp scrolls the view up half a page
func (h *BufPane) HalfPageUp() bool {
v := h.GetView()
if v.StartLine > v.Height/2 {
h.ScrollUp(v.Height / 2)
} else {
v.StartLine = 0
}
h.SetView(v)
h.ScrollUp(v.Height / 2)
return true
}
// HalfPageDown scrolls the view down half a page
func (h *BufPane) HalfPageDown() bool {
v := h.GetView()
if h.Buf.LinesNum()-(v.StartLine+v.Height) > v.Height/2 {
h.ScrollDown(v.Height / 2)
} else if h.Buf.LinesNum() >= v.Height {
v.StartLine = h.Buf.LinesNum() - v.Height
}
h.SetView(v)
h.ScrollDown(v.Height / 2)
h.ScrollAdjust()
return true
}
......
......@@ -21,13 +21,6 @@ func WriteLog(s string) {
buffer.WriteLog(s)
if LogBufPane != nil {
LogBufPane.CursorEnd()
v := LogBufPane.GetView()
endY := buffer.LogBuf.End().Y
if endY > v.StartLine+v.Height {
v.StartLine = buffer.LogBuf.End().Y - v.Height + 2
LogBufPane.SetView(v)
}
}
}
......@@ -37,12 +30,4 @@ func WriteLog(s string) {
func (h *BufPane) OpenLogBuf() {
LogBufPane = h.HSplitBuf(buffer.LogBuf)
LogBufPane.CursorEnd()
v := LogBufPane.GetView()
endY := buffer.LogBuf.End().Y
if endY > v.StartLine+v.Height {
v.StartLine = buffer.LogBuf.End().Y - v.Height + 2
LogBufPane.SetView(v)
}
}
......@@ -545,6 +545,27 @@ func (b *Buffer) RuneAt(loc Loc) rune {
return '\n'
}
// WordAt returns the word around a given location in the buffer
func (b *Buffer) WordAt(loc Loc) []byte {
if len(b.LineBytes(loc.Y)) == 0 || !util.IsWordChar(b.RuneAt(loc)) {
return []byte{}
}
start := loc
end := loc.Move(1, b)
for start.X > 0 && util.IsWordChar(b.RuneAt(start.Move(-1, b))) {
start.X--
}
lineLen := util.CharacterCount(b.LineBytes(loc.Y))
for end.X < lineLen && util.IsWordChar(b.RuneAt(end)) {
end.X++
}
return b.Substr(start, end)
}
// Modified returns if this buffer has been modified since
// being opened
func (b *Buffer) Modified() bool {
......
......@@ -106,51 +106,35 @@ func (w *BufWindow) Clear() {
}
}
// Bottomline returns the line number of the lowest line in the view
// You might think that this is obviously just v.StartLine + v.Height
// but if softwrap is enabled things get complicated since one buffer
// line can take up multiple lines in the view
func (w *BufWindow) Bottomline() int {
if !w.Buf.Settings["softwrap"].(bool) {
h := w.StartLine + w.Height - 1
if w.drawStatus {
h--
}
return h
}
l := w.LocFromVisual(buffer.Loc{0, w.Y + w.Height})
return l.Y
}
// Relocate moves the view window so that the cursor is in view
// This is useful if the user has scrolled far away, and then starts typing
// Returns true if the window location is moved
func (w *BufWindow) Relocate() bool {
b := w.Buf
// how many buffer lines are in the view
height := w.Bottomline() + 1 - w.StartLine
h := w.Height
height := w.Height
if w.drawStatus {
h--
height--
}
ret := false
activeC := w.Buf.GetActiveCursor()
cy := activeC.Y
scrollmargin := int(b.Settings["scrollmargin"].(float64))
if cy < w.StartLine+scrollmargin && cy > scrollmargin-1 {
w.StartLine = cy - scrollmargin
c := w.SLocFromLoc(activeC.Loc)
bStart := SLoc{0, 0}
bEnd := w.SLocFromLoc(b.End())
if c.LessThan(w.Scroll(w.StartLine, scrollmargin)) && c.GreaterThan(w.Scroll(bStart, scrollmargin-1)) {
w.StartLine = w.Scroll(c, -scrollmargin)
ret = true
} else if cy < w.StartLine {
w.StartLine = cy
} else if c.LessThan(w.StartLine) {
w.StartLine = c
ret = true
}
if cy > w.StartLine+height-1-scrollmargin && cy < b.LinesNum()-scrollmargin {
w.StartLine = cy - height + 1 + scrollmargin
if c.GreaterThan(w.Scroll(w.StartLine, height-1-scrollmargin)) && c.LessThan(w.Scroll(bEnd, -scrollmargin+1)) {
w.StartLine = w.Scroll(c, -height+1+scrollmargin)
ret = true
} else if cy >= b.LinesNum()-scrollmargin && cy >= height {
w.StartLine = b.LinesNum() - height
} else if c.GreaterThan(w.Scroll(bEnd, -scrollmargin)) && c.GreaterThan(w.Scroll(w.StartLine, height-1)) {
w.StartLine = w.Scroll(bEnd, -height+1)
ret = true
}
......@@ -199,11 +183,15 @@ func (w *BufWindow) LocFromVisual(svloc buffer.Loc) buffer.Loc {
// this represents the current draw position
// within the current window
vloc := buffer.Loc{X: 0, Y: 0}
if softwrap {
// the start line may be partially out of the current window
vloc.Y = -w.StartLine.Row
}
// this represents the current draw position in the buffer (char positions)
bloc := buffer.Loc{X: -1, Y: w.StartLine}
bloc := buffer.Loc{X: -1, Y: w.StartLine.Line}
for vloc.Y = 0; vloc.Y < bufHeight; vloc.Y++ {
for ; vloc.Y < bufHeight; vloc.Y++ {
vloc.X = 0
if hasMessage {
vloc.X += 2
......@@ -473,14 +461,18 @@ func (w *BufWindow) displayBuffer() {
// this represents the current draw position
// within the current window
vloc := buffer.Loc{X: 0, Y: 0}
if softwrap {
// the start line may be partially out of the current window
vloc.Y = -w.StartLine.Row
}
// this represents the current draw position in the buffer (char positions)
bloc := buffer.Loc{X: -1, Y: w.StartLine}
bloc := buffer.Loc{X: -1, Y: w.StartLine.Line}
cursors := b.GetCursors()
curStyle := config.DefStyle
for vloc.Y = 0; vloc.Y < bufHeight; vloc.Y++ {
for ; vloc.Y < bufHeight; vloc.Y++ {
vloc.X = 0
currentLine := false
......@@ -496,16 +488,28 @@ func (w *BufWindow) displayBuffer() {
s = curNumStyle
}
if hasMessage {
w.drawGutter(&vloc, &bloc)
}
if vloc.Y >= 0 {
if hasMessage {
w.drawGutter(&vloc, &bloc)
}
if b.Settings["diffgutter"].(bool) {
w.drawDiffGutter(s, false, &vloc, &bloc)
}
if b.Settings["diffgutter"].(bool) {
w.drawDiffGutter(s, false, &vloc, &bloc)
}
if b.Settings["ruler"].(bool) {
w.drawLineNum(s, false, maxLineNumLength, &vloc, &bloc)
if b.Settings["ruler"].(bool) {
w.drawLineNum(s, false, maxLineNumLength, &vloc, &bloc)
}
} else {
if hasMessage {
vloc.X += 2
}
if b.Settings["diffgutter"].(bool) {
vloc.X++
}
if b.Settings["ruler"].(bool) {
vloc.X += maxLineNumLength + 1
}
}
w.gutterOffset = vloc.X
......@@ -517,7 +521,7 @@ func (w *BufWindow) displayBuffer() {
bloc.X = bslice
draw := func(r rune, combc []rune, style tcell.Style, showcursor bool) {
if nColsBeforeStart <= 0 {
if nColsBeforeStart <= 0 && vloc.Y >= 0 {
_, origBg, _ := style.Decompose()
_, defBg, _ := config.DefStyle.Decompose()
......@@ -590,6 +594,8 @@ func (w *BufWindow) displayBuffer() {
}
}
}
}
if nColsBeforeStart <= 0 {
vloc.X++
}
nColsBeforeStart--
......@@ -735,7 +741,7 @@ func (w *BufWindow) displayScrollBar() {
if barsize < 1 {
barsize = 1
}
barstart := w.Y + int(float64(w.StartLine)/float64(w.Buf.LinesNum())*float64(w.Height))
barstart := w.Y + int(float64(w.StartLine.Line)/float64(w.Buf.LinesNum())*float64(w.Height))
scrollBarStyle := config.DefStyle.Reverse(true)
if style, ok := config.Colorscheme["scrollbar"]; ok {
......
......@@ -72,6 +72,10 @@ func (i *InfoWindow) LocFromVisual(vloc buffer.Loc) buffer.Loc {
return buffer.Loc{c.GetCharPosInLine(l, vloc.X-n), 0}
}
func (i *InfoWindow) Scroll(s SLoc, n int) SLoc { return s }
func (i *InfoWindow) Diff(s1, s2 SLoc) int { return 0 }
func (i *InfoWindow) SLocFromLoc(loc buffer.Loc) SLoc { return SLoc{0, 0} }
func (i *InfoWindow) Clear() {
for x := 0; x < i.Width; x++ {
screen.SetContent(x, i.Y, ' ', nil, i.defStyle())
......
package display
import (
"github.com/zyedidia/micro/v2/internal/buffer"
"github.com/zyedidia/micro/v2/internal/util"
)
// SLoc represents a vertical scrolling location, i.e. a location of a visual line
// in the buffer. When softwrap is enabled, a buffer line may be displayed as
// multiple visual lines (rows). So SLoc stores a number of a line in the buffer
// and a number of a row within this line.
type SLoc struct {
Line, Row int
}
// LessThan returns true if s is less b
func (s SLoc) LessThan(b SLoc) bool {
if s.Line < b.Line {
return true
}
return s.Line == b.Line && s.Row < b.Row
}
// GreaterThan returns true if s is bigger than b
func (s SLoc) GreaterThan(b SLoc) bool {
if s.Line > b.Line {
return true
}
return s.Line == b.Line && s.Row > b.Row
}
type SoftWrap interface {
Scroll(s SLoc, n int) SLoc
Diff(s1, s2 SLoc) int
SLocFromLoc(loc buffer.Loc) SLoc
}
func (w *BufWindow) getRow(loc buffer.Loc) int {
width := w.Width - w.gutterOffset
if w.Buf.Settings["scrollbar"].(bool) && w.Buf.LinesNum() > w.Height {
width--
}
if width <= 0 {
return 0
}
// TODO: this doesn't work quite correctly if there is an incomplete tab
// or wide character at the end of a row. See also issue #1979
x := util.StringWidth(w.Buf.LineBytes(loc.Y), loc.X, util.IntOpt(w.Buf.Settings["tabsize"]))
return x / width
}
func (w *BufWindow) getRowCount(line int) int {
return w.getRow(buffer.Loc{X: util.CharacterCount(w.Buf.LineBytes(line)), Y: line}) + 1
}
func (w *BufWindow) scrollUp(s SLoc, n int) SLoc {
for n > 0 {
if n <= s.Row {
s.Row -= n
n = 0
} else if s.Line > 0 {
s.Line--
n -= s.Row + 1
s.Row = w.getRowCount(s.Line) - 1
} else {
s.Row = 0
break
}
}
return s
}
func (w *BufWindow) scrollDown(s SLoc, n int) SLoc {
for n > 0 {
rc := w.getRowCount(s.Line)
if n < rc-s.Row {
s.Row += n
n = 0
} else if s.Line < w.Buf.LinesNum()-1 {
s.Line++
n -= rc - s.Row
s.Row = 0
} else {
s.Row = rc - 1
break
}
}
return s
}
func (w *BufWindow) scroll(s SLoc, n int) SLoc {
if n < 0 {
return w.scrollUp(s, -n)
}
return w.scrollDown(s, n)
}
func (w *BufWindow) diff(s1, s2 SLoc) int {
n := 0
for s1.LessThan(s2) {
if s1.Line < s2.Line {
n += w.getRowCount(s1.Line) - s1.Row
s1.Line++
s1.Row = 0
} else {
n += s2.Row - s1.Row
s1.Row = s2.Row
}
}
return n
}
// Scroll returns the location which is n visual lines below the location s
// i.e. the result of scrolling n lines down. n can be negative,
// which means scrolling up. The returned location is guaranteed to be
// within the buffer boundaries.
func (w *BufWindow) Scroll(s SLoc, n int) SLoc {
if !w.Buf.Settings["softwrap"].(bool) {
s.Line += n
if s.Line < 0 {
s.Line = 0
}
if s.Line > w.Buf.LinesNum()-1 {
s.Line = w.Buf.LinesNum() - 1
}
return s
}
return w.scroll(s, n)
}
// Diff returns the difference (the vertical distance) between two SLocs.
func (w *BufWindow) Diff(s1, s2 SLoc) int {
if !w.Buf.Settings["softwrap"].(bool) {
return s2.Line - s1.Line
}
if s1.GreaterThan(s2) {
return -w.diff(s2, s1)
}
return w.diff(s1, s2)
}
// SLocFromLoc takes a position in the buffer and returns the location
// of the visual line containing this position.
func (w *BufWindow) SLocFromLoc(loc buffer.Loc) SLoc {
if !w.Buf.Settings["softwrap"].(bool) {
return SLoc{loc.Y, 0}
}
return SLoc{loc.Y, w.getRow(loc)}
}
......@@ -8,10 +8,13 @@ type View struct {
X, Y int // X,Y location of the view
Width, Height int // Width and height of the view
// Start line and start column of the view (vertical/horizontal scroll)
// Start line of the view (for vertical scroll)
StartLine SLoc
// Start column of the view (for horizontal scroll)
// note that since the starting column of every line is different if the view
// is scrolled, StartCol is a visual index (will be the same for every line)
StartLine, StartCol int
StartCol int
}
type Window interface {
......@@ -28,5 +31,6 @@ type Window interface {
type BWindow interface {
Window
SoftWrap
SetBuffer(b *buffer.Buffer)
}
......@@ -259,6 +259,7 @@ The packages and functions are listed below (in Go type signatures):
- `MTError` error message.
- `Loc(x, y int) Loc`: creates a new location struct.
- `SLoc(line, row int) display.SLoc`: creates a new scrolling location struct.
- `BTDefault`: default buffer type.
- `BTLog`: log buffer type.
......
filetype: patch
detect:
detect:
filename: "\\.(patch|diff)$"
header: "^diff"
rules:
- brightgreen: "^\\+.*"
......
filetype: perl6
filetype: raku
detect:
filename: "(\\.p6$|\\.pl6$|\\.pm6$)"
filename: "(\\.p6$|\\.pl6$|\\.pm6$|\\.raku$|\\.rakumod$|\\.rakudoc$)"
rules:
- type: "\\b(accept|alarm|atan2|bin(d|mode)|c(aller|h(dir|mod|op|own|root)|lose(dir)?|onnect|os|rypt)|d(bm(close|open)|efined|elete|ie|o|ump)|e(ach|of|val|x(ec|ists|it|p))|f(cntl|ileno|lock|ork)|get(c|login|peername|pgrp|ppid|priority|pwnam|(host|net|proto|serv)byname|pwuid|grgid|(host|net)byaddr|protobynumber|servbyport)|([gs]et|end)(pw|gr|host|net|proto|serv)ent|getsock(name|opt)|gmtime|goto|grep|hex|index|int|ioctl|join|keys|kill|last|length|link|listen|local(time)?|log|lstat|m|mkdir|msg(ctl|get|snd|rcv)|next|oct|open(dir)?|ord|pack|pipe|pop|printf?|push|q|qq|qx|rand|re(ad(dir|link)?|cv|do|name|quire|set|turn|verse|winddir)|rindex|rmdir|s|scalar|seek|seekdir|se(lect|mctl|mget|mop|nd|tpgrp|tpriority|tsockopt)|shift|shm(ctl|get|read|write)|shutdown|sin|sleep|socket(pair)?|sort|spli(ce|t)|sprintf|sqrt|srand|stat|study|substr|symlink|sys(call|read|tem|write)|tell(dir)?|time|tr|y|truncate|umask|un(def|link|pack|shift)|utime|values|vec|wait(pid)?|wantarray|warn|write)\\b"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册