mirror of
https://github.com/akiyosi/goneovim.git
synced 2025-08-05 10:34:36 +02:00
228 lines
4.9 KiB
Go
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() {
|
|
}
|