mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-10 14:42:47 +09:00
Infobar prompts
This commit is contained in:
@@ -34,18 +34,18 @@ func (h *BufHandler) ScrollDown(n int) {
|
||||
// MousePress is the event that should happen when a normal click happens
|
||||
// This is almost always bound to left click
|
||||
func (h *BufHandler) MousePress(e *tcell.EventMouse) bool {
|
||||
h.ScrollUp(h.Buf.Settings["scrollspeed"].(int))
|
||||
return false
|
||||
}
|
||||
|
||||
// ScrollUpAction scrolls the view up
|
||||
func (h *BufHandler) ScrollUpAction() bool {
|
||||
h.ScrollUp(util.IntOpt(h.Buf.Settings["scrollspeed"]))
|
||||
return false
|
||||
}
|
||||
|
||||
// ScrollDownAction scrolls the view up
|
||||
func (h *BufHandler) ScrollDownAction() bool {
|
||||
h.ScrollDown(h.Buf.Settings["scrollspeed"].(int))
|
||||
h.ScrollDown(util.IntOpt(h.Buf.Settings["scrollspeed"]))
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -298,6 +298,38 @@ func (h *BufHandler) InsertSpace() bool {
|
||||
|
||||
// InsertNewline inserts a newline plus possible some whitespace if autoindent is on
|
||||
func (h *BufHandler) InsertNewline() bool {
|
||||
if h.Buf.Type == buffer.BTInfo {
|
||||
info.MainBar.DonePrompt(false)
|
||||
return false
|
||||
}
|
||||
|
||||
// Insert a newline
|
||||
if h.Cursor.HasSelection() {
|
||||
h.Cursor.DeleteSelection()
|
||||
h.Cursor.ResetSelection()
|
||||
}
|
||||
|
||||
ws := util.GetLeadingWhitespace(h.Buf.LineBytes(h.Cursor.Y))
|
||||
cx := h.Cursor.X
|
||||
h.Buf.Insert(h.Cursor.Loc, "\n")
|
||||
// h.Cursor.Right()
|
||||
|
||||
if h.Buf.Settings["autoindent"].(bool) {
|
||||
if cx < len(ws) {
|
||||
ws = ws[0:cx]
|
||||
}
|
||||
h.Buf.Insert(h.Cursor.Loc, string(ws))
|
||||
// for i := 0; i < len(ws); i++ {
|
||||
// h.Cursor.Right()
|
||||
// }
|
||||
|
||||
// Remove the whitespaces if keepautoindent setting is off
|
||||
if util.IsSpacesOrTabs(h.Buf.LineBytes(h.Cursor.Y-1)) && !h.Buf.Settings["keepautoindent"].(bool) {
|
||||
line := h.Buf.LineBytes(h.Cursor.Y - 1)
|
||||
h.Buf.Remove(buffer.Loc{X: 0, Y: h.Cursor.Y - 1}, buffer.Loc{X: utf8.RuneCount(line), Y: h.Cursor.Y - 1})
|
||||
}
|
||||
}
|
||||
h.Cursor.LastVisualX = h.Cursor.GetVisualX()
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -402,7 +434,7 @@ func (h *BufHandler) OutdentLine() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
for x := 0; x < len(h.Buf.IndentString(h.Buf.Settings["tabsize"].(int))); x++ {
|
||||
for x := 0; x < len(h.Buf.IndentString(util.IntOpt(h.Buf.Settings["tabsize"]))); x++ {
|
||||
if len(util.GetLeadingWhitespace(h.Buf.LineBytes(h.Cursor.Y))) == 0 {
|
||||
break
|
||||
}
|
||||
@@ -426,7 +458,7 @@ func (h *BufHandler) OutdentSelection() bool {
|
||||
startY := start.Y
|
||||
endY := end.Move(-1, h.Buf).Y
|
||||
for y := startY; y <= endY; y++ {
|
||||
for x := 0; x < len(h.Buf.IndentString(h.Buf.Settings["tabsize"].(int))); x++ {
|
||||
for x := 0; x < len(h.Buf.IndentString(util.IntOpt(h.Buf.Settings["tabsize"]))); x++ {
|
||||
if len(util.GetLeadingWhitespace(h.Buf.LineBytes(y))) == 0 {
|
||||
break
|
||||
}
|
||||
@@ -442,7 +474,7 @@ func (h *BufHandler) OutdentSelection() bool {
|
||||
|
||||
// InsertTab inserts a tab or spaces
|
||||
func (h *BufHandler) InsertTab() bool {
|
||||
indent := h.Buf.IndentString(h.Buf.Settings["tabsize"].(int))
|
||||
indent := h.Buf.IndentString(util.IntOpt(h.Buf.Settings["tabsize"]))
|
||||
tabBytes := len(indent)
|
||||
bytesUntilIndent := tabBytes - (h.Cursor.GetVisualX() % tabBytes)
|
||||
h.Buf.Insert(h.Cursor.Loc, indent[:bytesUntilIndent])
|
||||
@@ -609,6 +641,14 @@ func (h *BufHandler) SelectAll() bool {
|
||||
|
||||
// OpenFile opens a new file in the buffer
|
||||
func (h *BufHandler) OpenFile() bool {
|
||||
cb := func(resp string, canceled bool) {
|
||||
if !canceled {
|
||||
info.MainBar.Message("Opening", resp)
|
||||
} else {
|
||||
info.MainBar.Error("Canceled")
|
||||
}
|
||||
}
|
||||
info.MainBar.Prompt("Open file: ", cb)
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ var (
|
||||
BTLog = BufType{2, true, true, false}
|
||||
BTScratch = BufType{3, false, true, false}
|
||||
BTRaw = BufType{4, true, true, false}
|
||||
BTInfo = BufType{5, false, true, false}
|
||||
)
|
||||
|
||||
// Buffer stores the main information about a currently open file including
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package display
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
runewidth "github.com/mattn/go-runewidth"
|
||||
"github.com/zyedidia/micro/cmd/micro/buffer"
|
||||
"github.com/zyedidia/micro/cmd/micro/config"
|
||||
"github.com/zyedidia/micro/cmd/micro/info"
|
||||
"github.com/zyedidia/micro/cmd/micro/screen"
|
||||
"github.com/zyedidia/micro/cmd/micro/util"
|
||||
"github.com/zyedidia/tcell"
|
||||
)
|
||||
|
||||
@@ -56,19 +58,99 @@ func (i *InfoWindow) Clear() {
|
||||
}
|
||||
}
|
||||
|
||||
func (i *InfoWindow) displayBuffer() {
|
||||
b := i.Buffer
|
||||
line := b.LineBytes(0)
|
||||
activeC := b.GetActiveCursor()
|
||||
|
||||
blocX := 0
|
||||
vlocX := utf8.RuneCountInString(i.Msg)
|
||||
|
||||
tabsize := 4
|
||||
line, nColsBeforeStart := util.SliceVisualEnd(line, blocX, tabsize)
|
||||
|
||||
draw := func(r rune, style tcell.Style) {
|
||||
if nColsBeforeStart <= 0 {
|
||||
bloc := buffer.Loc{X: blocX, Y: 0}
|
||||
if activeC.HasSelection() &&
|
||||
(bloc.GreaterEqual(activeC.CurSelection[0]) && bloc.LessThan(activeC.CurSelection[1]) ||
|
||||
bloc.LessThan(activeC.CurSelection[0]) && bloc.GreaterEqual(activeC.CurSelection[1])) {
|
||||
// The current character is selected
|
||||
style = config.DefStyle.Reverse(true)
|
||||
|
||||
if s, ok := config.Colorscheme["selection"]; ok {
|
||||
style = s
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
screen.Screen.SetContent(vlocX, i.y, r, nil, style)
|
||||
vlocX++
|
||||
}
|
||||
nColsBeforeStart--
|
||||
}
|
||||
|
||||
totalwidth := blocX - nColsBeforeStart
|
||||
for len(line) > 0 {
|
||||
if activeC.X == blocX {
|
||||
screen.Screen.ShowCursor(vlocX, i.y)
|
||||
}
|
||||
|
||||
r, size := utf8.DecodeRune(line)
|
||||
|
||||
draw(r, i.defStyle)
|
||||
|
||||
width := 0
|
||||
|
||||
char := ' '
|
||||
switch r {
|
||||
case '\t':
|
||||
ts := tabsize - (totalwidth % tabsize)
|
||||
width = ts
|
||||
default:
|
||||
width = runewidth.RuneWidth(r)
|
||||
char = '@'
|
||||
}
|
||||
|
||||
blocX++
|
||||
line = line[size:]
|
||||
|
||||
// Draw any extra characters either spaces for tabs or @ for incomplete wide runes
|
||||
if width > 1 {
|
||||
for j := 1; j < width; j++ {
|
||||
draw(char, i.defStyle)
|
||||
}
|
||||
}
|
||||
totalwidth += width
|
||||
if vlocX >= i.width {
|
||||
break
|
||||
}
|
||||
}
|
||||
if activeC.X == blocX {
|
||||
screen.Screen.ShowCursor(vlocX, i.y)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *InfoWindow) Display() {
|
||||
x := 0
|
||||
if i.HasPrompt || config.GlobalSettings["infobar"].(bool) {
|
||||
if !i.HasPrompt && !i.HasMessage && !i.HasError {
|
||||
return
|
||||
}
|
||||
style := i.defStyle
|
||||
|
||||
if i.HasError {
|
||||
style = i.errStyle
|
||||
}
|
||||
|
||||
display := i.Msg + strings.TrimSpace(string(i.Bytes()))
|
||||
display := i.Msg
|
||||
for _, c := range display {
|
||||
screen.Screen.SetContent(x, i.y, c, nil, style)
|
||||
x += runewidth.RuneWidth(c)
|
||||
}
|
||||
|
||||
if i.HasPrompt {
|
||||
i.displayBuffer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package display
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strconv"
|
||||
"unicode/utf8"
|
||||
|
||||
@@ -81,9 +80,8 @@ func (w *BufWindow) Bottomline() int {
|
||||
// }
|
||||
|
||||
prev := 0
|
||||
for i, l := range w.lineHeight {
|
||||
for _, l := range w.lineHeight {
|
||||
if l >= prev {
|
||||
log.Println("lineHeight[", i, "] = ", l)
|
||||
prev = l
|
||||
} else {
|
||||
break
|
||||
@@ -98,7 +96,6 @@ func (w *BufWindow) Bottomline() int {
|
||||
func (w *BufWindow) Relocate() bool {
|
||||
b := w.Buf
|
||||
height := w.Bottomline() + 1 - w.StartLine
|
||||
log.Println("Height: ", height)
|
||||
ret := false
|
||||
activeC := w.Buf.GetActiveCursor()
|
||||
cy := activeC.Y
|
||||
@@ -115,7 +112,6 @@ func (w *BufWindow) Relocate() bool {
|
||||
ret = true
|
||||
} else if cy >= b.LinesNum()-scrollmargin && cy >= height {
|
||||
w.StartLine = b.LinesNum() - height
|
||||
log.Println(w.StartLine)
|
||||
ret = true
|
||||
}
|
||||
|
||||
@@ -217,7 +213,7 @@ func (w *BufWindow) displayBuffer() {
|
||||
// this represents the current draw position in the buffer (char positions)
|
||||
bloc := buffer.Loc{X: w.StartCol, Y: w.StartLine}
|
||||
|
||||
activeC := w.Buf.GetActiveCursor()
|
||||
activeC := b.GetActiveCursor()
|
||||
|
||||
curStyle := config.DefStyle
|
||||
for vloc.Y = 0; vloc.Y < bufHeight; vloc.Y++ {
|
||||
|
||||
@@ -2,6 +2,7 @@ package info
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/zyedidia/micro/cmd/micro/buffer"
|
||||
)
|
||||
@@ -30,13 +31,15 @@ type Bar struct {
|
||||
|
||||
// Is the current message a message from the gutter
|
||||
GutterMessage bool
|
||||
|
||||
PromptCallback func(resp string, canceled bool)
|
||||
}
|
||||
|
||||
func NewBar() *Bar {
|
||||
ib := new(Bar)
|
||||
ib.History = make(map[string][]string)
|
||||
|
||||
ib.Buffer = buffer.NewBufferFromString("", "infobar", buffer.BTScratch)
|
||||
ib.Buffer = buffer.NewBufferFromString("", "infobar", buffer.BTInfo)
|
||||
|
||||
return ib
|
||||
}
|
||||
@@ -60,7 +63,23 @@ func (i *Bar) Error(msg ...interface{}) {
|
||||
if i.HasPrompt == false {
|
||||
// if there is no active prompt then style and display the message as normal
|
||||
i.Msg = fmt.Sprint(msg...)
|
||||
i.HasError = true
|
||||
i.HasMessage, i.HasError = false, true
|
||||
}
|
||||
// TODO: add to log?
|
||||
}
|
||||
|
||||
func (i *Bar) Prompt(msg string, callback func(string, bool)) {
|
||||
i.Msg = msg
|
||||
i.HasPrompt = true
|
||||
i.HasMessage, i.HasError = false, false
|
||||
i.PromptCallback = callback
|
||||
}
|
||||
|
||||
func (i *Bar) DonePrompt(canceled bool) {
|
||||
i.HasPrompt = false
|
||||
if canceled {
|
||||
i.PromptCallback("", true)
|
||||
} else {
|
||||
i.PromptCallback(strings.TrimSpace(string(i.LineBytes(0))), false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,6 +212,7 @@ func main() {
|
||||
for {
|
||||
// Display everything
|
||||
screen.Screen.Fill(' ', config.DefStyle)
|
||||
screen.Screen.HideCursor()
|
||||
ep.Display()
|
||||
infowindow.Display()
|
||||
screen.Screen.Show()
|
||||
|
||||
@@ -155,6 +155,17 @@ func IsSpaces(str []byte) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsSpacesOrTabs checks if a given string contains only spaces and tabs
|
||||
func IsSpacesOrTabs(str []byte) bool {
|
||||
for _, c := range str {
|
||||
if c != ' ' && c != '\t' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// IsWhitespace returns true if the given rune is a space, tab, or newline
|
||||
func IsWhitespace(c rune) bool {
|
||||
return c == ' ' || c == '\t' || c == '\n'
|
||||
@@ -247,3 +258,8 @@ func GetLeadingWhitespace(b []byte) []byte {
|
||||
}
|
||||
return ws
|
||||
}
|
||||
|
||||
// IntOpt turns a float64 setting to an int
|
||||
func IntOpt(opt interface{}) int {
|
||||
return int(opt.(float64))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user