akiyosi.goneovim/editor/cmdline.go

332 lines
7.4 KiB
Go
Raw Permalink Normal View History

2017-11-09 02:11:05 +00:00
package editor
2017-06-28 11:06:47 +01:00
import (
"fmt"
"strings"
2019-03-05 23:09:22 +09:00
2019-11-02 10:54:41 +09:00
"github.com/akiyosi/goneovim/util"
2017-06-28 11:06:47 +01:00
)
// CmdContent is the content of the cmdline
type CmdContent struct {
firstc string
prompt string
content string
2021-12-10 21:24:04 +09:00
indent int
2017-06-28 11:06:47 +01:00
}
// Cmdline is the cmdline
type Cmdline struct {
2018-01-05 08:07:29 +00:00
ws *Workspace
2017-06-28 15:52:36 +01:00
content *CmdContent
preContent *CmdContent
function []*CmdContent
rawItems []interface{}
2021-12-10 21:24:04 +09:00
pos int
2017-06-28 15:52:36 +01:00
top int
2021-12-10 21:24:04 +09:00
shown bool
inFunction bool
wildmenuShown bool
2017-06-28 11:06:47 +01:00
}
func initCmdline() *Cmdline {
return &Cmdline{
2017-06-28 15:52:36 +01:00
content: &CmdContent{},
rawItems: make([]interface{}, 0),
2017-06-28 11:06:47 +01:00
}
}
func (c *CmdContent) getText() string {
indentStr := ""
for i := 0; i < c.indent; i++ {
indentStr += " "
}
return fmt.Sprintf("%s%s", indentStr, c.content)
}
func (c *Cmdline) getText(ch string) string {
indentStr := ""
for i := 0; i < c.content.indent; i++ {
indentStr += " "
}
2018-08-01 00:04:34 +09:00
if c.pos > len(c.content.content) {
c.pos = len(c.content.content) - 1
}
if len(c.content.content) == 0 {
c.pos = 0
}
2017-06-28 11:06:47 +01:00
return fmt.Sprintf("%s%s%s", c.content.firstc, indentStr, c.content.content[:c.pos]+ch+c.content.content[c.pos:])
}
2019-09-09 23:11:32 +09:00
func sanitize(s string) string {
s = strings.Replace(s, " ", `&nbsp;`, -1)
2019-09-22 13:26:37 +09:00
s = strings.Replace(s, "\t", `&nbsp;`, -1)
2019-09-09 23:11:32 +09:00
s = strings.Replace(s, "<", `&lt;`, -1)
s = strings.Replace(s, ">", `&gt;`, -1)
return s
}
2017-06-28 11:06:47 +01:00
func (c *Cmdline) show(args []interface{}) {
if c.ws.palette == nil {
return
}
2019-09-09 23:11:32 +09:00
palette := c.ws.palette
2017-06-28 11:06:47 +01:00
arg := args[0].([]interface{})
content := ""
2019-09-08 21:40:15 +09:00
contentChunks := arg[0].([]interface{})
for _, e := range contentChunks {
a := e.([]interface{})
if len(a) < 2 {
2019-09-09 23:11:32 +09:00
// content += a[0].(string)
2019-09-22 13:26:37 +09:00
content += strings.Replace(a[0].(string), "\t", " ", -1)
} else {
color := c.ws.foreground
_, ok := c.ws.screen.hlAttrDef[util.ReflectToInt(a[0])]
if ok {
color = c.ws.screen.hlAttrDef[util.ReflectToInt(a[0])].foreground
}
2019-09-29 00:17:37 +09:00
// I don't know how to set sticking out direction of
2019-09-08 21:40:15 +09:00
// the contents of a qlabel with html text to the left.
if len(contentChunks) == 1 {
2019-09-09 23:11:32 +09:00
// content += a[1].(string)
2019-09-22 13:26:37 +09:00
content += strings.Replace(a[1].(string), "\t", " ", -1)
2019-09-08 21:40:15 +09:00
} else {
content += fmt.Sprintf(
"<font color='%s'>%s</font>",
color.Hex(),
2019-09-09 23:11:32 +09:00
sanitize(a[1].(string)),
2019-09-08 21:40:15 +09:00
)
2019-09-09 23:11:32 +09:00
palette.isHTMLText = true
2019-09-08 21:40:15 +09:00
}
}
}
// content := arg[0].([]interface{})[0].([]interface{})[1].(string)
2019-03-05 23:09:22 +09:00
pos := util.ReflectToInt(arg[1])
2017-06-28 11:06:47 +01:00
firstc := arg[2].(string)
prompt := arg[3].(string)
2019-03-05 23:09:22 +09:00
indent := util.ReflectToInt(arg[4])
// level := util.ReflectToInt(arg[5])
2017-06-28 11:06:47 +01:00
// fmt.Println("cmdline show", content, pos, firstc, prompt, indent, level)
c.pos = pos
c.content.firstc = firstc
2018-10-31 12:12:57 +09:00
isResize := c.content.content != content
2017-06-28 11:06:47 +01:00
c.content.content = content
c.content.indent = indent
c.content.prompt = prompt
text := c.getText("")
palette.setPattern(text)
c.shown = true
2017-06-28 11:06:47 +01:00
c.cursorMove()
2018-10-31 12:12:57 +09:00
if isResize {
palette.resize()
}
2017-06-28 15:52:36 +01:00
if !c.wildmenuShown {
c.showAddition()
palette.scrollCol.Hide()
}
2017-11-09 01:41:26 +00:00
palette.show()
2017-06-28 11:06:47 +01:00
}
func (c *Cmdline) showAddition() {
if c.ws.palette == nil {
return
}
2017-06-28 11:06:47 +01:00
lines := append(c.getPromptLines(), c.getFunctionLines()...)
2018-01-05 08:07:29 +00:00
palette := c.ws.palette
2017-06-28 11:06:47 +01:00
for i, resultItem := range palette.resultItems {
2017-06-28 15:52:36 +01:00
if i >= len(lines) || i >= palette.showTotal {
2017-06-28 11:06:47 +01:00
resultItem.hide()
continue
}
resultItem.setItem(lines[i], "", []int{})
resultItem.setSelected(false)
resultItem.show()
}
}
func (c *Cmdline) getPromptLines() []string {
result := []string{}
if c.content.prompt == "" {
return result
}
lines := strings.Split(c.content.prompt, "\n")
for _, line := range lines {
if strings.TrimSpace(line) == "" {
continue
}
result = append(result, line)
}
return result
}
func (c *Cmdline) getFunctionLines() []string {
result := []string{}
if !c.inFunction {
return result
}
for _, content := range c.function {
result = append(result, content.getText())
}
return result
}
func (c *Cmdline) cursorMove() {
if c.ws.palette == nil {
return
}
2018-01-05 08:07:29 +00:00
c.ws.palette.cursorMove(c.pos + len(c.content.firstc) + c.content.indent)
2017-06-28 11:06:47 +01:00
}
2020-07-25 12:22:55 +09:00
func (c *Cmdline) hide() {
if c.ws.palette == nil {
return
}
2018-01-05 08:07:29 +00:00
palette := c.ws.palette
2017-06-28 11:06:47 +01:00
palette.hide()
if c.inFunction {
c.function = append(c.function, c.content)
}
c.preContent = c.content
c.content = &CmdContent{}
2021-11-13 01:00:53 +09:00
c.shown = false
win, ok := c.ws.screen.getWindow(c.ws.cursor.gridid)
if !ok {
return
}
2021-05-27 21:41:50 +09:00
if c.ws.cursor.isInPalette {
win.setUIParent()
2021-11-13 01:00:53 +09:00
c.ws.cursor.raise()
2021-05-27 21:41:50 +09:00
c.ws.cursor.x = c.ws.cursor.x + float64(c.ws.palette.widget.Pos().X())
c.ws.cursor.y = c.ws.cursor.y + float64(c.ws.palette.widget.Pos().Y())
}
2019-08-21 16:58:17 +09:00
2017-06-28 11:06:47 +01:00
}
func (c *Cmdline) functionShow() {
c.inFunction = true
c.function = []*CmdContent{c.preContent}
}
func (c *Cmdline) functionHide() {
c.inFunction = false
}
func (c *Cmdline) changePos(args []interface{}) {
args = args[0].([]interface{})
2019-03-05 23:09:22 +09:00
pos := util.ReflectToInt(args[0])
// level := util.ReflectToInt(args[1])
2017-06-28 11:06:47 +01:00
// fmt.Println("change pos", pos, level)
c.pos = pos
c.cursorMove()
}
func (c *Cmdline) putChar(args []interface{}) {
if c.ws.palette == nil {
return
}
2017-06-28 11:06:47 +01:00
args = args[0].([]interface{})
ch := args[0].(string)
2019-03-05 23:09:22 +09:00
// shift := util.ReflectToInt(args[1])
// level := util.ReflectToInt(args[2])
2017-06-28 11:06:47 +01:00
// fmt.Println("putChar", ch, shift, level)
text := c.getText(ch)
2018-01-05 08:07:29 +00:00
palette := c.ws.palette
2017-06-28 11:06:47 +01:00
palette.setPattern(text)
}
2017-06-28 15:52:36 +01:00
2019-08-21 16:58:17 +09:00
func (c *Cmdline) cmdWildmenuShow(args []interface{}) {
if c.ws.palette == nil {
return
}
2019-08-21 16:58:17 +09:00
c.wildmenuShown = true
for _, arg := range args {
c.rawItems = (arg.([]interface{}))[0].([]interface{})
palette := c.ws.palette
c.top = 0
for i := 0; i < palette.showTotal; i++ {
resultItem := palette.resultItems[i]
if i >= len(c.rawItems) {
resultItem.hide()
continue
}
text := (c.rawItems[i].([]interface{}))[0].(string)
resultItem.setItem(text, "", []int{})
resultItem.show()
resultItem.setSelected(false)
}
total := len(c.rawItems)
if total > palette.showTotal {
height := int(float64(palette.showTotal) / float64(total) * float64(palette.itemHeight*palette.showTotal))
if height == 0 {
height = 1
}
palette.scrollBar.SetFixedHeight(height)
palette.scrollBarPos = 0
palette.scrollBar.Move2(0, palette.scrollBarPos)
palette.scrollCol.Show()
} else {
palette.scrollCol.Hide()
}
}
}
func (c *Cmdline) cmdWildmenuSelect(args []interface{}) {
if c.ws.palette == nil {
return
}
2019-08-21 16:58:17 +09:00
selected := util.ReflectToInt(args[0].([]interface{})[0])
// fmt.Println("selected is", selected)
showTotal := c.ws.palette.showTotal
if selected == -1 && c.top > 0 {
c.cmdWildmenuScroll(-c.top)
}
if selected-c.top >= showTotal {
c.cmdWildmenuScroll(selected - c.top - showTotal + 1)
}
if selected >= 0 && selected-c.top < 0 {
c.cmdWildmenuScroll(-1)
}
palette := c.ws.palette
for i := 0; i < palette.showTotal; i++ {
item := palette.resultItems[i]
item.setSelected(selected == i+c.top)
}
}
func (c *Cmdline) cmdWildmenuScroll(n int) {
if c.ws.palette == nil {
return
}
2019-08-21 16:58:17 +09:00
c.top += n
palette := c.ws.palette
for i := 0; i < palette.showTotal; i++ {
resultItem := palette.resultItems[i]
if i >= len(c.rawItems) {
resultItem.hide()
continue
}
text := (c.rawItems[i+c.top].([]interface{}))[0].(string)
resultItem.setItem(text, "", []int{})
resultItem.show()
resultItem.setSelected(false)
}
palette.scrollBarPos = int((float64(c.top) / float64(len(c.rawItems))) * float64(palette.itemHeight*palette.showTotal))
palette.scrollBar.Move2(0, palette.scrollBarPos)
}
func (c *Cmdline) cmdWildmenuHide() {
c.wildmenuShown = false
}