akiyosi.goneovim/filer/filer.go
2023-07-19 08:38:12 +09:00

228 lines
4.9 KiB
Go

package filer
import (
"fmt"
"strings"
"github.com/akiyosi/goneovim/util"
"github.com/akiyosi/qt/widgets"
"github.com/neovim/go-client/nvim"
)
type Filer struct {
Widget *widgets.QListWidget
nvim *nvim.Nvim
selectnum int
items [](map[string]string)
openCmd string
}
// RegisterPlugin registers this remote plugin
func RegisterPlugin(nvim *nvim.Nvim, openCmd string) {
nvim.Subscribe("GonvimFiler")
f := &Filer{
nvim: nvim,
openCmd: openCmd,
}
nvim.RegisterHandler("GonvimFiler", func(args ...interface{}) {
go f.handle(args...)
})
finderFunction := `
aug GonvimAuFiler | au! | aug END
au GonvimAuFiler DirChanged * call rpcnotify(0, "Gui", "filer_update")
command! GonvimFilerOpen call Gonvim_filer_run()
function! Gonvim_filer_run() abort
call rpcnotify(0, "GonvimFiler", "open")
let l:keymaps = { "\<Esc>": "cancel", "\<C-c>": "cancel", "\<Enter>": "right", "h": "left", "j": "down", "k": "up", "l": "right", "/": "search", }
while v:true
let l:input = getchar()
let l:char = nr2char(l:input)
let event = get(l:keymaps, l:char, "noevent")
if (l:input is# "\<BS>")
call rpcnotify(0, "GonvimFiler", "up")
elseif (l:input is# "\<DEL>")
call rpcnotify(0, "GonvimFiler", "up")
elseif (event == "noevent")
call rpcnotify(0, "GonvimFiler", "char", l:char)
else
call rpcnotify(0, "GonvimFiler", event)
endif
if (event == "cancel")
call rpcnotify(0, "GonvimFiler", event)
return
endif
endwhile
endfunction
`
registerFunction := fmt.Sprintf(
`call execute(%s)`,
util.SplitVimscript(finderFunction),
)
nvim.Command(registerFunction)
}
func (f *Filer) handle(args ...interface{}) {
if len(args) < 1 {
return
}
event, ok := args[0].(string)
if !ok {
return
}
switch event {
case "cancel":
f.cancel()
case "open":
f.open()
case "redraw":
f.redraw()
case "left":
f.left()
case "right":
f.right()
case "up":
f.up()
case "down":
f.down()
case "search":
f.search()
default:
fmt.Println("unhandleld filer event", event)
}
}
func (f *Filer) open() {
f.nvim.Call("rpcnotify", nil, 0, "Gui", "side_open")
f.nvim.Call("rpcnotify", nil, 0, "Gui", "filer_open")
f.redraw()
}
func (f *Filer) redraw() {
f.nvim.Call("rpcnotify", nil, 0, "Gui", "filer_clear")
var files string
var err error
err = f.nvim.ExecLua(`
local uv = vim and vim.loop or require 'luv'
local path = vim.fn.expand(vim.fn.getcwd())
local h = uv.fs_scandir(path)
local result = ""
while true do
local name, type = uv.fs_scandir_next(h)
if not name then
break
end
if type == "directory" then
result = result .. "\n" .. name .. "/"
else
result = result .. "\n" .. name
end
end
return result
`, &files)
if err != nil {
return
}
var items []map[string]string
for _, file := range strings.Split(files, "\n") {
if file == "" {
continue
}
// Skip './' and '../'
if file == "./" || file == "../" {
continue
}
// Remove current dir string
parts := strings.SplitN(file, ".", -1)
filetype := ""
if len(parts) > 1 {
filetype = parts[len(parts)-1]
}
// If it is directory
if file[len(file)-1] == '/' {
filetype = string("/")
}
f.nvim.Call("rpcnotify", nil, 0, "Gui", "filer_item_add", file, filetype)
item := make(map[string]string)
item["filename"] = file
item["filetype"] = filetype
items = append(items, item)
}
f.items = items
f.nvim.Call("rpcnotify", nil, 0, "Gui", "filer_resize")
if f.selectnum >= len(f.items) {
f.selectnum = len(f.items) - 1
}
f.nvim.Call("rpcnotify", nil, 0, "Gui", "filer_item_select", f.selectnum)
}
func (f *Filer) up() {
f.selectnum--
if f.selectnum < 0 {
f.selectnum = 0
}
f.nvim.Call("rpcnotify", nil, 0, "Gui", "filer_item_select", f.selectnum)
}
func (f *Filer) down() {
f.selectnum++
if f.selectnum >= len(f.items) {
f.selectnum = len(f.items) - 1
}
f.nvim.Call("rpcnotify", nil, 0, "Gui", "filer_item_select", f.selectnum)
}
func (f *Filer) left() {
go func() {
f.nvim.Command("silent :tchdir ..")
}()
}
func (f *Filer) right() {
if f.selectnum >= len(f.items) {
return
}
item := f.items[f.selectnum]
filename, ok := item["filename"]
if !ok {
return
}
filetype, ok := item["filetype"]
if !ok {
return
}
command := ""
cdCommand := ":tchdir"
editCommand := f.openCmd
switch filetype {
case "/":
command = "silent " + cdCommand + " " + filename + " | <CR><CR> | :redraw!"
default:
command = "silent " + editCommand + " " + filename + " | <CR><CR> | :redraw!"
}
go func() {
f.nvim.Command(command)
if filetype != "/" {
f.nvim.Input("<Esc>")
// f.nvim.Command("GonvimFilerOpen")
}
}()
}
func (f *Filer) cancel() {
f.nvim.Call("rpcnotify", nil, 0, "Gui", "side_close")
}
// TODO
func (f *Filer) search() {
}