2017-11-09 02:11:05 +00:00
package editor
2017-03-14 01:52:44 +00:00
import (
"fmt"
2019-12-08 23:24:57 +09:00
"io/ioutil"
2020-12-23 00:07:42 +09:00
"log"
2018-01-08 10:23:16 +00:00
"os"
2019-12-08 23:24:57 +09:00
"os/exec"
2018-01-08 10:23:16 +00:00
"path/filepath"
2017-05-12 04:07:54 +01:00
"runtime"
2018-01-08 10:23:16 +00:00
"strconv"
2017-03-14 07:20:31 +00:00
"strings"
2017-06-02 10:41:28 +01:00
"sync"
2020-12-21 19:57:18 +09:00
"time"
2021-07-25 22:35:17 +09:00
"unicode"
2017-03-14 01:52:44 +00:00
2020-06-06 22:33:04 +09:00
"github.com/akiyosi/goneovim/util"
2019-03-13 11:50:52 +09:00
frameless "github.com/akiyosi/goqtframelesswindow"
2020-09-03 22:13:48 +09:00
clipb "github.com/atotto/clipboard"
2019-11-19 00:32:34 +09:00
homedir "github.com/mitchellh/go-homedir"
2017-06-16 08:43:05 +01:00
"github.com/therecipe/qt/core"
2018-01-05 08:07:29 +00:00
"github.com/therecipe/qt/gui"
2017-06-06 02:42:11 +01:00
"github.com/therecipe/qt/widgets"
2017-03-14 01:52:44 +00:00
)
2021-08-06 23:13:30 +09:00
var Version string
2017-03-14 01:52:44 +00:00
var editor * Editor
2019-10-22 22:50:56 +09:00
const (
2021-08-06 23:13:30 +09:00
WORKSPACELEN = 10
2019-10-22 22:50:56 +09:00
)
2020-12-12 01:39:52 +09:00
type editorSignal struct {
core . QObject
_ func ( ) ` signal:"notifySignal" `
_ func ( ) ` signal:"sidebarSignal" `
}
2018-12-27 21:03:21 +09:00
// ColorPalette is
2018-12-27 12:38:42 +09:00
type ColorPalette struct {
2019-06-12 22:14:48 +09:00
e * Editor
2019-06-12 21:58:35 +09:00
2018-12-31 16:43:04 +09:00
fg * RGBA
bg * RGBA
inactiveFg * RGBA
comment * RGBA
abyss * RGBA
matchFg * RGBA
selectedBg * RGBA
sideBarFg * RGBA
sideBarBg * RGBA
sideBarSelectedItemBg * RGBA
scrollBarFg * RGBA
scrollBarBg * RGBA
widgetFg * RGBA
widgetBg * RGBA
widgetInputArea * RGBA
minimapCurrentRegion * RGBA
2019-05-31 16:41:37 +09:00
windowSeparator * RGBA
2019-06-07 02:00:14 +09:00
indentGuide * RGBA
2018-12-27 12:38:42 +09:00
}
2019-06-30 19:35:25 +09:00
// NotifyButton is
type NotifyButton struct {
action func ( )
text string
}
2018-12-21 12:18:41 +09:00
// Notify is
2018-08-16 19:31:36 +09:00
type Notify struct {
message string
buttons [ ] * NotifyButton
2021-12-10 21:24:04 +09:00
level NotifyLevel
period int
2018-08-16 19:31:36 +09:00
}
2020-12-23 00:07:42 +09:00
type Options struct {
2022-04-19 11:49:35 +09:00
Geometry string ` long:"geometry" description:"Initial window geomtry [e.g. --geometry=800x600]" `
Server string ` long:"server" description:"Remote session address [e.g. --server=host:3456]" `
Ssh string ` long:"ssh" description:"Attaching to a remote nvim via ssh. Default port is 22. [e.g. --ssh=user@host:port]" `
Nvim string ` long:"nvim" description:"Excutable nvim path to attach [e.g. --nvim=/path/to/nvim]" `
Debug string ` long:"debug" description:"Run debug mode with debug.log(default) file [e.g. --debug=/path/to/my-debug.log]" optional:"yes" optional-value:"debug.log" `
Fullscreen bool ` long:"fullscreen" description:"Open the window in fullscreen on startup" `
Maximized bool ` long:"maximized" description:"Maximize the window on startup" `
Exttabline bool ` long:"exttabline" description:"Externalize the tabline" `
Extcmdline bool ` long:"extcmdline" description:"Externalize the cmdline" `
Extmessages bool ` long:"extmessages" description:"Externalize the messages. Sets --extcmdline implicitly" `
Extpopupmenu bool ` long:"extpopupmenu" description:"Externalize the popupmenu" `
Version bool ` long:"version" description:"Print Goneovim version" `
Wsl * string ` long:"wsl" description:"Attach to nvim process in wsl environment with distribution(default) [e.g. --wsl=Ubuntu]" optional:"yes" optional-value:"" `
2019-11-13 22:49:25 +09:00
}
2017-03-14 01:52:44 +00:00
// Editor is the editor
type Editor struct {
2022-03-01 14:30:47 +09:00
stop chan int
2021-12-10 21:24:04 +09:00
signal * editorSignal
app * widgets . QApplication
font * Font
widget * widgets . QWidget
splitter * widgets . QSplitter
window * frameless . QFramelessWindow
specialKeys map [ core . Qt__Key ] string
svgs map [ string ] * SvgXML
notifyStartPos * core . QPoint
colors * ColorPalette
notify chan * Notify
cbChan chan * string
sysTray * widgets . QSystemTrayIcon
side * WorkspaceSide
2022-04-09 22:13:43 +09:00
savedGeometry * core . QByteArray
2021-12-10 21:24:04 +09:00
prefixToMapMetaKey string
macAppArg string
extFontFamily string
configDir string
homeDir string
version string
2018-12-31 16:43:04 +09:00
config gonvimConfig
2021-12-10 21:24:04 +09:00
opts Options
2018-12-31 16:43:04 +09:00
notifications [ ] * Notification
2021-12-10 21:24:04 +09:00
workspaces [ ] * Workspace
args [ ] string
ppid int
keyControl core . Qt__Key
keyCmd core . Qt__Key
width int
active int
startuptime int64
iconSize int
height int
extFontSize int
notificationWidth int
stopOnce sync . Once
muMetaKey sync . Mutex
isSetGuiColor bool
2018-12-27 12:38:42 +09:00
isDisplayNotifications bool
2021-12-10 21:24:04 +09:00
isKeyAutoRepeating bool
sessionExists bool
2022-03-04 17:28:52 +09:00
isWindowResized bool
2017-06-16 08:43:05 +01:00
}
2017-03-14 01:52:44 +00:00
func ( hl * Highlight ) copy ( ) Highlight {
highlight := Highlight { }
if hl . foreground != nil {
highlight . foreground = hl . foreground . copy ( )
}
if hl . background != nil {
highlight . background = hl . background . copy ( )
}
2018-05-12 22:48:15 +09:00
highlight . bold = hl . bold
highlight . italic = hl . italic
2017-03-14 01:52:44 +00:00
return highlight
}
2017-06-06 02:42:11 +01:00
2017-11-09 02:11:05 +00:00
// InitEditor is
2021-08-06 23:13:30 +09:00
func InitEditor ( options Options , args [ ] string ) {
2020-12-23 00:07:42 +09:00
// startup time
startuptime := time . Now ( ) . UnixNano ( ) / 1000
// create editor struct
editor = & Editor {
2021-08-06 23:13:30 +09:00
version : Version ,
2020-12-23 00:07:42 +09:00
args : args ,
opts : options ,
startuptime : startuptime ,
2020-12-21 19:57:18 +09:00
}
2020-12-23 00:07:42 +09:00
e := editor
2020-12-21 19:57:18 +09:00
2020-12-23 00:07:42 +09:00
// log
var file * os . File
var err error
2021-01-25 23:24:53 +09:00
if e . opts . Debug != "" {
file , err = os . OpenFile ( e . opts . Debug , os . O_RDWR | os . O_CREATE | os . O_APPEND , 0666 )
2020-12-23 00:07:42 +09:00
if err != nil {
2021-01-25 23:24:53 +09:00
fmt . Println ( err )
2020-12-23 00:07:42 +09:00
os . Exit ( 1 )
}
log . SetOutput ( file )
log . SetFlags ( log . LstdFlags | log . Lmicroseconds )
}
e . putLog ( "--- GONEOVIM STARTING ---" )
2020-12-04 23:14:06 +09:00
2020-12-23 00:07:42 +09:00
e . signal = NewEditorSignal ( nil )
2022-03-01 14:30:47 +09:00
e . stop = make ( chan int )
2020-12-23 00:07:42 +09:00
e . notify = make ( chan * Notify , 10 )
e . cbChan = make ( chan * string , 240 )
2020-12-21 19:57:18 +09:00
2020-08-01 14:22:34 +09:00
// detect home dir
2018-04-26 17:41:43 +09:00
home , err := homedir . Dir ( )
2018-08-19 23:29:26 +09:00
if err != nil {
home = "~"
}
2020-12-23 00:07:42 +09:00
e . putLog ( "detecting home directory path" )
2020-12-21 19:57:18 +09:00
2020-12-04 23:14:06 +09:00
configDir , config := newConfig ( home )
2020-12-23 00:07:42 +09:00
e . config = config
2021-12-10 21:24:04 +09:00
if e . opts . Exttabline {
e . config . Editor . ExtTabline = true
}
if e . opts . Extcmdline {
e . config . Editor . ExtCmdline = true
}
if e . opts . Extpopupmenu {
e . config . Editor . ExtPopupmenu = true
}
if e . opts . Extmessages {
e . config . Editor . ExtMessages = true
e . config . Editor . ExtCmdline = true
}
2021-10-09 23:46:07 +09:00
2020-12-23 00:07:42 +09:00
e . homeDir = home
e . configDir = configDir
e . putLog ( "reading config" )
2020-12-21 19:57:18 +09:00
2020-08-01 14:22:34 +09:00
// application
2020-12-23 00:07:42 +09:00
e . putLog ( "start generating the application" )
core . QCoreApplication_SetAttribute ( core . Qt__AA_EnableHighDpiScaling , true )
2019-11-24 12:52:15 +09:00
e . app = widgets . NewQApplication ( len ( os . Args ) , os . Args )
2020-10-05 23:02:44 +09:00
e . ppid = os . Getppid ( )
2020-12-23 00:07:42 +09:00
e . putLog ( "finished generating the application" )
2020-12-21 19:57:18 +09:00
2020-12-27 21:32:52 +09:00
// put shell environment
// TODO: This process runs on a Unix-like OS, but it is very slow. I want to improve it.
e . setEnv ( )
e . putLog ( "setting environment variable" )
2020-08-01 14:22:34 +09:00
// set application working directory path
2022-04-23 01:31:11 +09:00
// TODO: This process is problematic and needs a better way to set up CWD
// * https://github.com/akiyosi/goneovim/issues/43
// * https://github.com/akiyosi/goneovim/issues/337
// * https://github.com/akiyosi/goneovim/issues/325
// e.setAppDirPath(home)
2020-12-23 00:07:42 +09:00
e . putLog ( "set working directory path" )
2020-06-06 22:33:04 +09:00
2020-12-24 23:45:33 +09:00
e . extFontFamily = e . config . Editor . FontFamily
e . extFontSize = e . config . Editor . FontSize
2020-12-05 14:36:12 +09:00
fontGenAsync := make ( chan * Font , 2 )
go func ( ) {
font := initFontNew (
editor . extFontFamily ,
float64 ( editor . extFontSize ) ,
0 ,
2021-11-30 23:15:52 +09:00
e . config . Editor . Letterspace ,
2020-12-05 14:36:12 +09:00
)
fontGenAsync <- font
} ( )
2021-02-09 22:26:24 +09:00
e . setFont ( )
2020-12-23 00:07:42 +09:00
e . putLog ( "initializing font" )
2020-12-21 19:57:18 +09:00
2020-12-11 21:59:47 +09:00
e . initSVGS ( )
2020-12-23 00:07:42 +09:00
e . putLog ( "initializing svg images" )
2020-12-11 21:59:47 +09:00
e . initColorPalette ( )
2020-12-23 00:07:42 +09:00
e . putLog ( "initializing color palette" )
2020-12-11 21:59:47 +09:00
e . initNotifications ( )
2020-12-23 00:07:42 +09:00
e . putLog ( "initializing notification UI" )
2020-12-11 21:59:47 +09:00
2020-12-23 00:07:42 +09:00
e . initSysTray ( )
2020-12-21 19:57:18 +09:00
2020-08-01 14:22:34 +09:00
// application main window
2020-12-21 19:57:18 +09:00
// e.window = widgets.NewQMainWindow(nil, 0)
2020-12-23 00:07:42 +09:00
e . putLog ( "start preparing the application window." )
2020-08-16 09:00:22 +09:00
isframeless := e . config . Editor . BorderlessWindow
2020-07-08 21:31:15 +09:00
e . window = frameless . CreateQFramelessWindow ( e . config . Editor . Transparent , isframeless )
2022-03-04 17:28:52 +09:00
e . window . SetupBorderSize ( e . config . Editor . Margin )
2021-01-29 01:29:06 +09:00
e . window . SetupWindowGap ( e . config . Editor . Gap )
2020-12-24 23:45:33 +09:00
e . setWindowSizeFromOpts ( )
2022-04-24 21:14:00 +09:00
e . showWindow ( )
2018-12-29 15:40:57 +09:00
e . setWindowOptions ( )
2020-12-24 01:07:16 +09:00
e . putLog ( "finished preparing the application window." )
2020-12-21 19:57:18 +09:00
2020-08-01 14:22:34 +09:00
// window layout
2019-06-12 21:58:35 +09:00
l := widgets . NewQBoxLayout ( widgets . QBoxLayout__RightToLeft , nil )
l . SetContentsMargins ( 0 , 0 , 0 , 0 )
l . SetSpacing ( 0 )
e . window . SetupContent ( l )
2019-05-14 12:56:46 +09:00
2020-08-01 14:22:34 +09:00
// window content
2020-12-04 23:14:06 +09:00
e . widget = widgets . NewQWidget ( nil , 0 )
2019-10-20 18:13:56 +09:00
e . newSplitter ( )
2020-12-11 21:59:47 +09:00
e . splitter . InsertWidget ( 1 , e . widget )
2020-08-28 00:54:52 +09:00
l . AddWidget ( e . splitter , 1 , 0 )
2020-12-23 00:07:42 +09:00
e . putLog ( "window layout done" )
2020-12-21 19:57:18 +09:00
2020-12-05 14:36:12 +09:00
e . font = <- fontGenAsync
2020-12-23 00:07:42 +09:00
e . putLog ( "done calculating the width of the font." )
2020-12-05 14:36:12 +09:00
2020-08-01 14:22:34 +09:00
// neovim workspaces
2019-10-24 17:04:33 +09:00
e . initWorkspaces ( )
2020-12-23 00:07:42 +09:00
e . putLog ( "done initialazing workspaces" )
2019-10-24 17:04:33 +09:00
2020-10-05 23:02:44 +09:00
e . connectAppSignals ( )
2020-12-12 01:39:52 +09:00
e . signal . ConnectSidebarSignal ( func ( ) {
2021-01-22 22:55:14 +09:00
if e . side != nil {
2020-12-15 00:41:02 +09:00
return
}
2021-02-01 22:30:09 +09:00
e . putLog ( "create workspace sidebar" )
2021-01-22 22:55:14 +09:00
e . side = newWorkspaceSide ( )
e . side . newScrollArea ( )
e . side . scrollarea . Hide ( )
e . side . scrollarea . SetWidget ( e . side . widget )
e . splitter . InsertWidget ( 0 , e . side . scrollarea )
side := e . side
2020-12-15 00:41:02 +09:00
if e . config . SideBar . Visible {
side . show ( )
}
2020-12-12 01:39:52 +09:00
} )
2022-02-11 11:53:54 +09:00
// When an application is closed with the Close button
2020-10-05 23:02:44 +09:00
e . window . ConnectCloseEvent ( func ( event * gui . QCloseEvent ) {
2022-02-11 11:53:54 +09:00
e . putLog ( "The application was closed outside of Neovim's commands, such as the Close button." )
e . cleanup ( )
e . saveAppWindowState ( )
if runtime . GOOS == "darwin" {
e . app . DisconnectEvent ( )
}
2020-10-05 23:02:44 +09:00
event . Accept ( )
} )
2019-06-12 21:58:35 +09:00
2020-08-01 14:22:34 +09:00
// runs goroutine to detect stop events and quit the application
2019-06-12 21:58:35 +09:00
go func ( ) {
2022-03-01 14:30:47 +09:00
ret := <- e . stop
close ( e . stop )
2022-02-11 11:53:54 +09:00
e . putLog ( "The application was quitted with the exit of Neovim." )
2019-06-12 21:58:35 +09:00
if runtime . GOOS == "darwin" {
e . app . DisconnectEvent ( )
}
2022-02-11 11:53:54 +09:00
e . saveAppWindowState ( )
2022-03-01 14:30:47 +09:00
// e.app.Quit()
os . Exit ( ret )
2019-06-12 21:58:35 +09:00
} ( )
2020-11-28 01:28:56 +09:00
// launch thread to copy text to the clipboard in darwin
if runtime . GOOS == "darwin" {
if e . config . Editor . Clipboard {
go func ( ) {
for {
2020-12-03 00:37:08 +09:00
select {
case <- e . stop :
return
default :
text := <- e . cbChan
e . app . Clipboard ( ) . SetText ( * text , gui . QClipboard__Clipboard )
}
2020-11-28 01:28:56 +09:00
}
} ( )
}
}
2020-12-23 00:07:42 +09:00
e . putLog ( "done connecting UI siganal" )
2020-11-28 01:28:56 +09:00
2020-12-12 01:39:52 +09:00
e . widget . SetFocus2 ( )
2020-12-23 00:07:42 +09:00
e . putLog ( "focused UI" )
2021-08-27 23:17:25 +09:00
e . addDockMenu ( )
2020-07-12 01:20:22 +09:00
2019-06-12 21:58:35 +09:00
widgets . QApplication_Exec ( )
}
2020-12-23 00:07:42 +09:00
func ( e * Editor ) putLog ( v ... interface { } ) {
2021-01-25 23:24:53 +09:00
if e . opts . Debug == "" {
2020-12-23 00:07:42 +09:00
return
2020-12-04 23:14:06 +09:00
}
2020-12-23 00:07:42 +09:00
log . Println (
fmt . Sprintf ( "%07.3f" , float64 ( time . Now ( ) . UnixNano ( ) / 1000 - e . startuptime ) / 1000 ) ,
2022-01-13 17:57:38 +09:00
strings . TrimRight ( strings . TrimLeft ( fmt . Sprintf ( "%v" , v ) , "[" ) , "]" ) ,
2020-12-23 00:07:42 +09:00
)
2020-12-04 23:14:06 +09:00
}
2021-08-27 23:17:25 +09:00
// addDockMenu add the action menu for app in the Dock.
func ( e * Editor ) addDockMenu ( ) {
if runtime . GOOS != "darwin" {
return
}
appExecutable := core . QCoreApplication_ApplicationFilePath ( )
menu := widgets . NewQMenu ( nil )
action1 := menu . AddAction ( "New Instance" )
action1 . ConnectTriggered ( func ( checked bool ) {
go func ( ) {
cmd := exec . Command ( appExecutable )
cmd . Start ( )
} ( )
} )
action2 := menu . AddAction ( "New Instance with -u NONE" )
action2 . ConnectTriggered ( func ( checked bool ) {
go func ( ) {
cmd := exec . Command ( appExecutable , "-u" , "NONE" )
cmd . Start ( )
} ( )
} )
for key , string := range e . config . Editor . DockmenuActions {
action := menu . AddAction ( key )
strSlice := strings . Split ( string , " " )
action . ConnectTriggered ( func ( checked bool ) {
go func ( ) {
cmd := exec . Command ( appExecutable , strSlice ... )
cmd . Start ( )
} ( )
} )
}
menu . SetAsDockMenu ( )
}
2020-08-01 14:22:34 +09:00
// setAppDirPath
2020-10-05 23:02:44 +09:00
// Set the current working directory of the application to the HOME directory in darwin, linux.
2020-08-01 14:22:34 +09:00
// If this process is not executed, CWD is set to the root directory, and
// nvim plugins called as descendants of the application will not work due to lack of permission.
// e.g. #122
2020-10-05 23:02:44 +09:00
func ( e * Editor ) setAppDirPath ( home string ) {
if runtime . GOOS == "windows" {
return
}
if runtime . GOOS == "darwin" {
if ! ( e . ppid == 1 && e . macAppArg == "" ) {
return
}
}
if runtime . GOOS == "linux" {
if e . ppid != 1 {
return
}
}
2020-08-01 14:22:34 +09:00
path := core . QCoreApplication_ApplicationDirPath ( )
absHome , err := util . ExpandTildeToHomeDirectory ( home )
if err == nil {
if path != absHome {
qdir := core . NewQDir2 ( path )
qdir . SetCurrent ( absHome )
}
}
}
2019-10-20 18:13:56 +09:00
func ( e * Editor ) newSplitter ( ) {
splitter := widgets . NewQSplitter2 ( core . Qt__Horizontal , nil )
splitter . SetStyleSheet ( "* {background-color: rgba(0, 0, 0, 0);}" )
splitter . SetStretchFactor ( 1 , 100 )
splitter . SetObjectName ( "splitter" )
2020-08-28 00:54:52 +09:00
e . splitter = splitter
2019-10-20 18:13:56 +09:00
}
2019-06-12 21:58:35 +09:00
func ( e * Editor ) initWorkspaces ( ) {
2018-10-11 21:37:36 +09:00
e . workspaces = [ ] * Workspace { }
2019-11-21 01:01:51 +09:00
if e . config . Workspace . RestoreSession {
2020-07-15 23:00:23 +09:00
for i := 0 ; i <= WORKSPACELEN ; i ++ {
2020-10-01 00:11:46 +09:00
path := filepath . Join ( e . configDir , "sessions" , strconv . Itoa ( i ) + ".vim" )
2019-06-12 21:58:35 +09:00
_ , err := os . Stat ( path )
if err != nil {
break
2018-10-11 21:37:36 +09:00
}
2021-06-12 13:37:12 +09:00
e . sessionExists = true
2019-06-12 21:58:35 +09:00
ws , err := newWorkspace ( path )
if err != nil {
break
}
e . workspaces = append ( e . workspaces , ws )
2021-06-03 23:53:11 +09:00
ws . widget . SetParent ( e . widget )
2018-10-11 21:37:36 +09:00
}
}
2021-06-12 13:37:12 +09:00
if ! e . sessionExists {
2018-10-11 21:37:36 +09:00
ws , err := newWorkspace ( "" )
if err != nil {
return
}
e . workspaces = append ( e . workspaces , ws )
2021-06-03 23:53:11 +09:00
ws . widget . SetParent ( e . widget )
2018-10-11 21:37:36 +09:00
}
2019-06-12 21:58:35 +09:00
}
2018-10-11 21:37:36 +09:00
2020-10-05 23:02:44 +09:00
func ( e * Editor ) connectAppSignals ( ) {
if e . app == nil {
return
}
2019-06-12 21:58:35 +09:00
if runtime . GOOS != "darwin" {
return
}
e . app . ConnectEvent ( func ( event * core . QEvent ) bool {
switch event . Type ( ) {
case core . QEvent__FileOpen :
2019-11-02 10:54:41 +09:00
// If goneovim not launched on finder (it is started in terminal)
2020-10-05 23:02:44 +09:00
if e . ppid != 1 {
2019-06-12 22:14:48 +09:00
return false
2019-06-12 21:58:35 +09:00
}
fileOpenEvent := gui . NewQFileOpenEventFromPointer ( event . Pointer ( ) )
2020-10-05 23:02:44 +09:00
e . macAppArg = fileOpenEvent . File ( )
e . loadFileInDarwin ( )
2018-05-25 01:00:23 +09:00
}
2019-06-12 21:58:35 +09:00
return true
} )
2020-10-05 23:02:44 +09:00
}
2022-03-04 17:28:52 +09:00
func ( e * Editor ) resizeMainWindow ( ) {
2022-04-09 22:13:43 +09:00
cws := e . workspaces [ e . active ]
windowWidth , windowHeight := cws . updateSize ( )
2022-03-04 17:28:52 +09:00
2022-04-09 22:13:43 +09:00
if ! editor . config . Editor . WindowGeometryBasedOnFontmetrics {
return
}
2022-03-04 17:28:52 +09:00
2022-04-09 22:13:43 +09:00
// quantization of window geometry with font metrics as the smallest unit of change.
geometry := editor . window . Geometry ( )
width := geometry . Width ( )
height := geometry . Height ( )
2022-03-04 17:28:52 +09:00
2022-04-09 22:13:43 +09:00
if ! ( width == windowWidth && height == windowHeight ) {
2022-03-04 17:28:52 +09:00
e . window . Resize2 (
windowWidth ,
windowHeight ,
)
}
}
2020-10-05 23:02:44 +09:00
func ( e * Editor ) loadFileInDarwin ( ) {
if runtime . GOOS != "darwin" {
return
}
goneovim := e . workspaces [ e . active ] . nvim
isModified := ""
isModified , _ = goneovim . CommandOutput ( "echo &modified" )
if isModified == "1" {
goneovim . Command ( fmt . Sprintf ( ":tabe %s" , e . macAppArg ) )
} else {
2021-03-23 21:34:56 +09:00
goneovim . Command ( fmt . Sprintf ( "%s %s" , e . config . Editor . FileOpenCmd , e . macAppArg ) )
2020-10-05 23:02:44 +09:00
}
2018-01-05 08:07:29 +00:00
}
2018-12-29 17:31:44 +09:00
func ( e * Editor ) initNotifications ( ) {
e . notifications = [ ] * Notification { }
2019-06-12 21:58:35 +09:00
e . notificationWidth = e . config . Editor . Width * 2 / 3
2018-12-29 17:31:44 +09:00
e . notifyStartPos = core . NewQPoint2 ( e . width - e . notificationWidth - 10 , e . height - 30 )
e . signal . ConnectNotifySignal ( func ( ) {
notify := <- e . notify
if notify . message == "" {
return
}
if notify . buttons == nil {
e . popupNotification ( notify . level , notify . period , notify . message )
} else {
e . popupNotification ( notify . level , notify . period , notify . message , notifyOptionArg ( notify . buttons ) )
}
} )
}
2019-07-11 12:18:17 +09:00
func ( e * Editor ) initSysTray ( ) {
2019-07-20 17:34:13 +09:00
if ! e . config . Editor . DesktopNotifications {
return
}
2019-07-11 18:28:37 +09:00
pixmap := gui . NewQPixmap ( )
2019-07-12 00:28:27 +09:00
color := ""
size := 0.95
if runtime . GOOS == "darwin" {
2019-07-15 19:41:49 +09:00
color = "#434343"
2019-07-12 00:28:27 +09:00
size = 0.9
} else {
color = "#179A33"
}
svg := fmt . Sprintf ( ` <svg viewBox="0 0 128 128"><g transform="translate(2,3) scale(%f)"><path fill="%s" d="M72.6 80.5c.2.2.6.5.9.5h5.3c.3 0 .7-.3.9-.5l1.4-1.5c.2-.2.3-.4.3-.6l1.5-5.1c.1-.5 0-1-.3-1.3l-1.1-.9c-.2-.2-.6-.1-.9-.1h-4.8l-.2-.2-.1-.1c-.2 0-.4-.1-.6.1l-1.9 1.2c-.2 0-.3.5-.4.7l-1.6 4.9c-.2.5-.1 1.1.3 1.5l1.3 1.4zM73.4 106.9l-.4.1h-1.2l7.2-21.1c.2-.7-.1-1.5-.8-1.7l-.4-.1h-12.1c-.5.1-.9.5-1 1l-.7 2.5c-.2.7.3 1.3 1 1.5l.3-.1h1.8l-7.3 20.9c-.2.7.1 1.6.8 1.9l.4.3h11.2c.6 0 1.1-.5 1.3-1.1l.7-2.4c.3-.7-.1-1.5-.8-1.7zM126.5 87.2l-1.9-2.5v-.1c-.3-.3-.6-.6-1-.6h-7.2c-.4 0-.7.4-1 .6l-2 2.4h-3.1l-2.1-2.4v-.1c-.2-.3-.6-.5-1-.5h-4l20.2-20.2-22.6-22.4 20.2-20.8v-9l-2.8-3.6h-40.9l-3.3 3.5v2.9l-11.3-11.4-7.7 7.5-2.4-2.5h-40.4l-3.2 3.7v9.4l3 2.9h3v26.1l-14 14 14 14v32l5.2 2.9h11.6l9.1-9.5 21.6 21.6 14.5-14.5c.1.4.4.5.9.7l.4-.2h9.4c.6 0 1.1-.1 1.2-.6l.7-2c.2-.7-.1-1.3-.8-1.5l-.4.1h-.4l3.4-10.7 2.3-2.3h5l-5 15.9c-.2.7.2 1.1.9 1.4l.4-.2h9.1c.5 0 1-.1 1.2-.6l.8-1.8c.3-.7-.1-1.3-.7-1.6-.1-.1-.3 0-.5 0h-.4l4.2-13h6.1l-5.1 15.9c-.2.7.2 1.1.9 1.3l.4-.3h10c.5 0 1-.1 1.2-.6l.8-2c.3-.7-.1-1.3-.8-1.5-.1-.1-.3.1-.5.1h-.7l5.6-18.5c.2-.5.1-1.1-.1-1.4zm-63.8-82.3l11.3 11.3v4.7l3.4 4.1h1.6l-29 28v-28h3.3l2.7-4.2v-8.9l-.2-.3 6.9-6.7zm-59.8 59.2l12.1-12.1v24.2l-12.1-12.1zm38.9 38.3l58.4-60 21.4 21.5-20.2 20.2h-.1c-.3.1-.5.3-.7.5l-2.1 2.4h-2.9l-2.2-2.4c-.2-.3-.6-.6-1-.6h-8.8c-.6 0-1.1.4-1.3 1l-.8 2.5c-.2.7.1 1.3.8 1.6h1.5l-6.4 18.9-15.1 15.2-20.5-20.8z"></path></g></svg> ` , size , color )
2019-07-11 18:28:37 +09:00
pixmap . LoadFromData2 ( core . NewQByteArray2 ( svg , len ( svg ) ) , "SVG" , core . Qt__ColorOnly )
trayIcon := gui . NewQIcon2 ( pixmap )
2020-10-01 00:11:46 +09:00
image := filepath . Join ( e . configDir , "trayicon.png" )
2019-07-15 20:41:02 +09:00
if isFileExist ( image ) {
trayIcon = gui . NewQIcon5 ( image )
}
2019-07-11 12:18:17 +09:00
e . sysTray = widgets . NewQSystemTrayIcon2 ( trayIcon , e . app )
2019-07-11 15:47:36 +09:00
e . sysTray . Show ( )
2020-12-23 00:07:42 +09:00
e . putLog ( "initialize system tray" )
2019-07-11 12:18:17 +09:00
}
2020-12-27 21:32:52 +09:00
func ( e * Editor ) setEnv ( ) {
2021-05-03 09:58:59 +09:00
// For Linux
2019-06-12 21:58:35 +09:00
if runtime . GOOS == "linux" {
2021-05-03 09:58:59 +09:00
// // It was not a necessary process to export the following environment variables.
// exe, _ := os.Executable()
// dir, _ := filepath.Split(exe)
// _ = os.Setenv("LD_LIBRARY_PATH", dir+"lib")
// _ = os.Setenv("QT_PLUGIN_PATH", dir+"plugins")
// _ = os.Setenv("RESOURCE_NAME", "goneovim")
2019-06-12 21:58:35 +09:00
}
2021-05-03 09:58:59 +09:00
// If the OS is MacOS and the application is launched from an .app
2020-12-27 21:32:52 +09:00
if runtime . GOOS == "darwin" && e . ppid == 1 {
2019-12-07 13:19:58 +09:00
shell := os . Getenv ( "SHELL" )
if shell == "" {
shell = os . Getenv ( "/bin/bash" )
}
2020-12-28 18:43:54 +09:00
cmd := exec . Command ( shell , "-l" , "-c" , "env" , "-i" )
// cmd := exec.Command("printenv")
2019-12-07 13:19:58 +09:00
stdout , err := cmd . StdoutPipe ( )
if err != nil {
2021-02-01 22:30:09 +09:00
e . putLog ( err )
2019-12-07 13:19:58 +09:00
return
}
2019-12-08 23:24:57 +09:00
if err := cmd . Start ( ) ; err != nil {
2021-02-01 22:30:09 +09:00
e . putLog ( err )
2019-12-07 13:19:58 +09:00
return
}
output , err := ioutil . ReadAll ( stdout )
if err != nil {
2021-02-01 22:30:09 +09:00
e . putLog ( err )
2019-12-07 13:19:58 +09:00
stdout . Close ( )
return
}
for _ , b := range strings . Split ( string ( output ) , "\n" ) {
2020-10-24 23:44:27 +09:00
splits := strings . SplitN ( b , "=" , 2 )
2019-12-07 13:19:58 +09:00
if len ( splits ) > 1 {
_ = os . Setenv ( splits [ 0 ] , splits [ 1 ] )
}
}
}
2021-05-03 09:58:59 +09:00
// For Windows
// https://github.com/equalsraf/neovim-qt/issues/391
if runtime . GOOS == "windows" {
_ = os . Setenv ( "QT_AUTO_SCREEN_SCALE_FACTOR" , "1" )
}
2019-06-12 21:58:35 +09:00
}
2021-02-09 22:26:24 +09:00
func ( e * Editor ) setFont ( ) {
2019-09-15 23:09:46 +09:00
e . app . SetFont ( gui . NewQFont2 ( e . extFontFamily , e . extFontSize , 1 , false ) , "QWidget" )
e . app . SetFont ( gui . NewQFont2 ( e . extFontFamily , e . extFontSize , 1 , false ) , "QLabel" )
2019-06-12 21:58:35 +09:00
}
2018-08-19 23:29:26 +09:00
func ( e * Editor ) pushNotification ( level NotifyLevel , p int , message string , opt ... NotifyOptionArg ) {
2020-12-23 00:07:42 +09:00
a := NotifyOptions { }
2018-08-16 19:31:36 +09:00
for _ , o := range opt {
2020-12-23 00:07:42 +09:00
o ( & a )
2018-08-16 19:31:36 +09:00
}
n := & Notify {
level : level ,
2018-08-19 23:29:26 +09:00
period : p ,
2018-08-16 19:31:36 +09:00
message : message ,
2020-12-23 00:07:42 +09:00
buttons : a . buttons ,
2018-08-16 19:31:36 +09:00
}
e . notify <- n
e . signal . NotifySignal ( )
}
2018-08-19 23:29:26 +09:00
func ( e * Editor ) popupNotification ( level NotifyLevel , p int , message string , opt ... NotifyOptionArg ) {
2020-08-10 23:19:00 +09:00
e . updateNotificationPos ( )
2018-08-19 23:29:26 +09:00
notification := newNotification ( level , p , message , opt ... )
2018-08-15 17:44:53 +09:00
notification . widget . SetParent ( e . window )
notification . widget . AdjustSize ( )
x := e . notifyStartPos . X ( )
2018-08-18 16:13:44 +09:00
y := e . notifyStartPos . Y ( ) - notification . widget . Height ( ) - 4
2018-08-15 17:44:53 +09:00
notification . widget . Move2 ( x , y )
e . notifyStartPos = core . NewQPoint2 ( x , y )
2018-08-15 21:45:15 +09:00
e . notifications = append ( e . notifications , notification )
2018-08-15 17:44:53 +09:00
notification . show ( )
}
2019-06-12 21:58:35 +09:00
func ( e * Editor ) initColorPalette ( ) {
rgbAccent := hexToRGBA ( e . config . SideBar . AccentColor )
2018-12-28 01:40:33 +09:00
fg := newRGBA ( 180 , 185 , 190 , 1 )
bg := newRGBA ( 9 , 13 , 17 , 1 )
2019-06-12 21:58:35 +09:00
c := & ColorPalette {
e : e ,
2018-12-31 16:43:04 +09:00
bg : bg ,
fg : fg ,
2018-12-28 15:46:52 +09:00
selectedBg : bg . brend ( rgbAccent , 0.3 ) ,
2018-12-31 16:43:04 +09:00
matchFg : rgbAccent ,
2018-12-27 12:38:42 +09:00
}
2019-06-12 21:58:35 +09:00
e . colors = c
e . colors . update ( )
2018-12-27 12:38:42 +09:00
}
2018-12-27 21:03:21 +09:00
func ( c * ColorPalette ) update ( ) {
fg := c . fg
bg := c . bg
2020-08-16 09:00:22 +09:00
c . selectedBg = bg . brend ( hexToRGBA ( c . e . config . SideBar . AccentColor ) , 0.3 )
2019-03-20 22:41:06 +09:00
c . inactiveFg = warpColor ( bg , - 80 )
c . comment = warpColor ( fg , - 80 )
2018-12-28 01:40:33 +09:00
c . abyss = warpColor ( bg , 5 )
2019-03-20 22:41:06 +09:00
c . sideBarFg = warpColor ( fg , - 5 )
c . sideBarBg = warpColor ( bg , - 5 )
c . sideBarSelectedItemBg = warpColor ( bg , - 15 )
c . scrollBarFg = warpColor ( bg , - 20 )
2018-12-27 21:03:21 +09:00
c . scrollBarBg = bg
2019-03-20 22:41:06 +09:00
c . widgetFg = warpColor ( fg , 5 )
c . widgetBg = warpColor ( bg , - 10 )
c . widgetInputArea = warpColor ( bg , - 30 )
c . minimapCurrentRegion = warpColor ( bg , 20 )
2020-08-16 09:00:22 +09:00
if c . e . config . Editor . WindowSeparatorColor != "" {
c . windowSeparator = hexToRGBA ( c . e . config . Editor . WindowSeparatorColor )
} else if c . e . config . Editor . WindowSeparatorTheme == "light" && c . e . config . Editor . WindowSeparatorColor == "" {
if fg . R < 250 && fg . G < 250 && fg . B < 250 {
c . windowSeparator = warpColor ( fg , 10 )
} else {
c . windowSeparator = warpColor ( fg , - 10 )
}
} else if c . e . config . Editor . WindowSeparatorTheme == "dark" && c . e . config . Editor . WindowSeparatorColor == "" {
if bg . R > 10 && bg . G > 10 && bg . B > 10 {
c . windowSeparator = warpColor ( bg , 10 )
} else {
c . windowSeparator = warpColor ( bg , - 10 )
}
}
2019-10-29 21:53:26 +09:00
c . indentGuide = warpColor ( bg , - 30 )
2018-12-27 21:03:21 +09:00
}
func ( e * Editor ) updateGUIColor ( ) {
2020-12-23 00:07:42 +09:00
e . putLog ( "start updating UI color" )
2019-01-01 18:34:51 +09:00
e . workspaces [ e . active ] . updateWorkspaceColor ( )
2019-03-02 21:40:40 +09:00
2019-10-27 15:59:27 +09:00
// Do not use frameless drawing on linux
if runtime . GOOS == "linux" {
2020-12-12 01:39:52 +09:00
e . window . TitleBar . Hide ( )
e . window . WindowWidget . SetStyleSheet ( fmt . Sprintf ( " #QFramelessWidget { background-color: rgba(%d, %d, %d, %f); border-radius: 0px;}" , e . colors . bg . R , e . colors . bg . G , e . colors . bg . B , e . config . Editor . Transparent ) )
e . window . SetWindowFlag ( core . Qt__FramelessWindowHint , false )
e . window . SetWindowFlag ( core . Qt__NoDropShadowWindowHint , false )
e . window . Show ( )
2019-10-27 15:59:27 +09:00
} else {
2020-12-12 01:39:52 +09:00
e . window . SetupWidgetColor ( ( uint16 ) ( e . colors . bg . R ) , ( uint16 ) ( e . colors . bg . G ) , ( uint16 ) ( e . colors . bg . B ) )
e . window . SetupTitleColor ( ( uint16 ) ( e . colors . fg . R ) , ( uint16 ) ( e . colors . fg . G ) , ( uint16 ) ( e . colors . fg . B ) )
2019-05-09 23:22:43 +09:00
}
2020-08-10 23:19:00 +09:00
// e.window.SetWindowOpacity(1.0)
2020-12-23 00:07:42 +09:00
e . putLog ( "finished updating UI color" )
2018-12-27 21:03:21 +09:00
}
2018-06-24 13:36:41 +09:00
func hexToRGBA ( hex string ) * RGBA {
format := "#%02x%02x%02x"
if len ( hex ) == 4 {
format = "#%1x%1x%1x"
}
var r , g , b uint8
n , err := fmt . Sscanf ( hex , format , & r , & g , & b )
if err != nil {
return nil
}
if n != 3 {
return nil
}
rgba := & RGBA {
R : ( int ) ( r ) ,
G : ( int ) ( g ) ,
B : ( int ) ( b ) ,
A : 1 ,
}
return rgba
}
2020-03-14 20:30:30 +09:00
func ( e * Editor ) setWindowSizeFromOpts ( ) {
2019-11-19 00:02:56 +09:00
if e . opts . Geometry == "" {
return
}
2020-03-14 20:30:30 +09:00
width , height := e . setWindowSize ( e . opts . Geometry )
e . config . Editor . Width = width
e . config . Editor . Height = height
}
2019-11-19 00:02:56 +09:00
2020-03-14 20:30:30 +09:00
func ( e * Editor ) setWindowSize ( s string ) ( int , int ) {
2019-11-19 00:02:56 +09:00
var width , height int
2020-03-14 20:30:30 +09:00
var err error
width , err = strconv . Atoi ( strings . SplitN ( s , "x" , 2 ) [ 0 ] )
2022-04-24 21:14:00 +09:00
if err != nil || width < 40 {
width = 40
2019-11-19 00:02:56 +09:00
}
2020-03-14 20:30:30 +09:00
height , err = strconv . Atoi ( strings . SplitN ( s , "x" , 2 ) [ 1 ] )
2022-04-24 21:14:00 +09:00
if err != nil || height < 30 {
height = 30
2020-03-14 20:30:30 +09:00
}
return width , height
2019-11-19 00:02:56 +09:00
}
2022-02-11 11:53:54 +09:00
func ( e * Editor ) restoreWindow ( ) ( isRestoreGeometry , isRestoreState bool ) {
if ! e . config . Editor . RestoreWindowGeometry {
return
}
settings := core . NewQSettings ( "neovim" , "goneovim" , nil )
geometry := settings . Value ( "geometry" , core . NewQVariant13 ( core . NewQByteArray ( ) ) )
state := settings . Value ( "windowState" , core . NewQVariant13 ( core . NewQByteArray ( ) ) )
geometryBA := geometry . ToByteArray ( )
stateBA := state . ToByteArray ( )
if geometryBA . Length ( ) != 0 {
e . window . RestoreGeometry ( geometryBA )
isRestoreGeometry = true
}
if stateBA . Length ( ) != 0 {
e . window . RestoreState ( stateBA , 0 )
isRestoreState = true
}
return
}
2018-12-29 15:40:57 +09:00
func ( e * Editor ) setWindowOptions ( ) {
2020-12-12 01:39:52 +09:00
e . window . SetupTitle ( "Neovim" )
2022-04-12 18:09:46 +09:00
e . window . SetMinimumSize2 ( 40 , 30 )
2020-12-12 01:39:52 +09:00
e . initSpecialKeys ( )
2018-12-29 15:40:57 +09:00
e . window . ConnectKeyPressEvent ( e . keyPress )
2021-01-13 21:09:14 +09:00
e . window . ConnectKeyReleaseEvent ( e . keyRelease )
2020-03-22 22:51:13 +09:00
e . window . SetAttribute ( core . Qt__WA_KeyCompression , false )
2018-12-29 15:40:57 +09:00
e . window . SetAcceptDrops ( true )
}
2020-08-12 00:02:45 +09:00
func ( e * Editor ) showWindow ( ) {
e . width = e . config . Editor . Width
e . height = e . config . Editor . Height
2022-02-11 11:53:54 +09:00
isRestoreGeometry , isRestoreState := e . restoreWindow ( )
2022-03-11 21:16:50 +09:00
// If command line options are given, they take priority.
if e . opts . Fullscreen || e . opts . Maximized {
if e . opts . Fullscreen {
2022-02-11 11:53:54 +09:00
e . window . WindowFullScreen ( )
2022-03-11 21:16:50 +09:00
} else if e . opts . Maximized {
2022-02-11 11:53:54 +09:00
e . window . WindowMaximize ( )
}
2022-03-11 21:16:50 +09:00
} else {
if ! isRestoreGeometry {
e . window . Resize2 ( e . width , e . height )
}
if ! isRestoreState {
if e . config . Editor . StartFullscreen {
e . window . WindowFullScreen ( )
} else if e . config . Editor . StartMaximizedWindow {
e . window . WindowMaximize ( )
}
}
2022-02-11 11:53:54 +09:00
}
2022-04-19 11:49:35 +09:00
if e . opts . Ssh == "" || e . opts . Wsl == nil {
2020-11-15 10:24:06 +09:00
e . window . Show ( )
}
2020-08-12 00:02:45 +09:00
}
2018-04-19 21:07:48 +09:00
func isFileExist ( filename string ) bool {
2018-04-30 16:58:26 +09:00
_ , err := os . Stat ( filename )
return err == nil
2018-04-19 21:07:48 +09:00
}
2018-06-13 21:08:02 +09:00
func ( e * Editor ) copyClipBoard ( ) {
2020-08-23 14:59:22 +09:00
var yankedText string
yankedText , _ = e . workspaces [ e . active ] . nvim . CommandOutput ( "echo getreg()" )
if yankedText != "" {
2020-09-03 22:13:48 +09:00
if runtime . GOOS != "darwin" {
clipb . WriteAll ( yankedText )
} else {
2020-11-28 01:28:56 +09:00
e . cbChan <- & yankedText
2020-09-03 22:13:48 +09:00
}
2020-08-23 14:59:22 +09:00
}
2018-06-16 10:15:40 +09:00
2018-06-13 21:08:02 +09:00
}
2018-01-05 09:13:50 +00:00
func ( e * Editor ) workspaceNew ( ) {
2021-05-13 23:52:40 +09:00
if len ( e . workspaces ) == WORKSPACELEN {
2021-02-14 16:27:43 +09:00
return
}
2018-12-28 13:53:55 +09:00
editor . isSetGuiColor = false
2018-01-11 06:11:34 +00:00
ws , err := newWorkspace ( "" )
2018-01-05 09:13:50 +00:00
if err != nil {
return
}
2018-05-20 12:06:29 +09:00
2018-01-05 09:13:50 +00:00
e . workspaces = append ( e . workspaces , nil )
2018-05-01 19:50:47 +09:00
e . active = len ( e . workspaces ) - 1
2018-01-05 09:13:50 +00:00
e . workspaces [ e . active ] = ws
2018-01-08 10:23:16 +00:00
}
func ( e * Editor ) workspaceSwitch ( index int ) {
index --
if index < 0 || index >= len ( e . workspaces ) {
return
}
e . active = index
2018-01-05 09:13:50 +00:00
e . workspaceUpdate ( )
}
func ( e * Editor ) workspaceNext ( ) {
e . active ++
if e . active >= len ( e . workspaces ) {
e . active = 0
}
e . workspaceUpdate ( )
}
2018-01-11 06:11:34 +00:00
func ( e * Editor ) workspacePrevious ( ) {
e . active --
if e . active < 0 {
e . active = len ( e . workspaces ) - 1
}
e . workspaceUpdate ( )
}
2018-01-05 09:13:50 +00:00
func ( e * Editor ) workspaceUpdate ( ) {
2021-01-22 22:55:14 +09:00
if e . side == nil {
2018-12-28 22:28:21 +09:00
return
}
2018-01-05 09:13:50 +00:00
for i , ws := range e . workspaces {
if i == e . active {
2021-05-05 10:31:34 +09:00
ws . hide ( )
2018-01-05 09:13:50 +00:00
ws . show ( )
} else {
ws . hide ( )
}
}
2021-01-22 22:55:14 +09:00
for i := 0 ; i < len ( e . side . items ) && i < len ( e . workspaces ) ; i ++ {
2021-05-08 01:58:26 +09:00
if e . side . items [ i ] == nil {
continue
}
2021-05-08 08:42:19 +09:00
if e . side . items [ i ] . label . Text ( ) == "" {
e . workspaces [ i ] . setCwd ( e . workspaces [ i ] . cwdlabel )
}
2021-01-22 22:55:14 +09:00
e . side . items [ i ] . setSideItemLabel ( i )
2021-05-05 10:31:34 +09:00
// e.side.items[i].setText(e.workspaces[i].cwdlabel)
2021-01-22 22:55:14 +09:00
e . side . items [ i ] . show ( )
2018-01-08 10:23:16 +00:00
}
2021-01-22 22:55:14 +09:00
for i := len ( e . workspaces ) ; i < len ( e . side . items ) ; i ++ {
2021-05-08 01:58:26 +09:00
if e . side . items [ i ] == nil {
continue
}
2021-01-22 22:55:14 +09:00
e . side . items [ i ] . hide ( )
2018-01-08 10:23:16 +00:00
}
2018-01-05 09:13:50 +00:00
}
2021-01-13 21:09:14 +09:00
func ( e * Editor ) keyRelease ( event * gui . QKeyEvent ) {
if ! e . isKeyAutoRepeating {
return
}
2021-12-23 18:08:23 +09:00
2021-12-28 02:18:15 +09:00
if editor . config . Editor . SmoothScroll {
ws := e . workspaces [ e . active ]
win , ok := ws . screen . getWindow ( ws . cursor . gridid )
if ! ok {
return
}
if win . scrollPixels2 != 0 {
return
}
2022-02-14 21:10:32 +09:00
win . grabScreenSnapshot ( win . Rect ( ) )
2021-12-28 02:18:15 +09:00
}
2021-01-13 21:09:14 +09:00
e . isKeyAutoRepeating = false
}
2018-01-05 08:07:29 +00:00
func ( e * Editor ) keyPress ( event * gui . QKeyEvent ) {
2021-12-23 18:08:23 +09:00
ws := e . workspaces [ e . active ]
2021-12-28 02:18:15 +09:00
if ! e . isKeyAutoRepeating {
2021-12-23 18:08:23 +09:00
ws . getSnapshot ( )
}
2020-03-24 00:03:42 +09:00
input := e . convertKey ( event )
2021-01-13 21:09:14 +09:00
if event . IsAutoRepeat ( ) {
e . isKeyAutoRepeating = true
}
2018-01-05 08:07:29 +00:00
if input != "" {
2018-01-05 09:13:50 +00:00
e . workspaces [ e . active ] . nvim . Input ( input )
2017-06-06 02:42:11 +01:00
}
2018-01-05 08:07:29 +00:00
}
2017-06-06 02:42:11 +01:00
2021-07-25 22:35:17 +09:00
func keyToText ( key int , mod core . Qt__KeyboardModifier ) string {
text := string ( rune ( key ) )
if ! ( mod & core . Qt__ShiftModifier > 0 ) {
text = strings . ToLower ( text )
}
return text
}
2022-04-02 14:31:56 +09:00
// controlModifier is
func controlModifier ( ) ( controlModifier core . Qt__KeyboardModifier ) {
if runtime . GOOS == "windows" {
controlModifier = core . Qt__ControlModifier
}
if runtime . GOOS == "linux" {
controlModifier = core . Qt__ControlModifier
}
2021-07-25 22:35:17 +09:00
if runtime . GOOS == "darwin" {
controlModifier = core . Qt__MetaModifier
}
2022-04-02 14:31:56 +09:00
return
2021-07-25 22:35:17 +09:00
}
2022-04-02 14:31:56 +09:00
// cmdModifier is
func cmdModifier ( ) ( cmdModifier core . Qt__KeyboardModifier ) {
2021-07-25 22:35:17 +09:00
if runtime . GOOS == "windows" {
cmdModifier = core . Qt__NoModifier
}
if runtime . GOOS == "linux" {
cmdModifier = core . Qt__MetaModifier
}
2022-04-02 14:31:56 +09:00
if runtime . GOOS == "darwin" {
cmdModifier = core . Qt__ControlModifier
}
2021-07-25 22:35:17 +09:00
2022-04-02 14:31:56 +09:00
return
2021-07-25 22:35:17 +09:00
}
2021-07-30 12:01:15 +09:00
func isAsciiCharRequiringAlt ( key int , mod core . Qt__KeyboardModifier , c rune ) bool {
// Ignore all key events where Alt is not pressed
if ! ( mod & core . Qt__AltModifier > 0 ) {
return false
}
// These low-ascii characters may require AltModifier on MacOS
if ( c == '[' && key != int ( core . Qt__Key_BracketLeft ) ) ||
( c == ']' && key != int ( core . Qt__Key_BracketRight ) ) ||
( c == '{' && key != int ( core . Qt__Key_BraceLeft ) ) ||
( c == '}' && key != int ( core . Qt__Key_BraceRight ) ) ||
( c == '|' && key != int ( core . Qt__Key_Bar ) ) ||
( c == '~' && key != int ( core . Qt__Key_AsciiTilde ) ) ||
( c == '@' && key != int ( core . Qt__Key_At ) ) {
return true
}
return false
}
2020-03-24 00:03:42 +09:00
func ( e * Editor ) convertKey ( event * gui . QKeyEvent ) string {
text := event . Text ( )
key := event . Key ( )
mod := event . Modifiers ( )
2022-04-02 14:31:56 +09:00
if e . opts . Debug != "" {
e . putLog ( "key input:" , fmt . Sprintf ( "%s, %d, %v" , text , key , mod ) )
}
2020-05-30 20:39:21 +09:00
// this is macmeta alternatively
2021-08-29 16:01:00 +09:00
if e . config . Editor . Macmeta {
if mod & core . Qt__AltModifier > 0 && mod & core . Qt__ShiftModifier > 0 {
text = string ( rune ( key ) )
} else if mod & core . Qt__AltModifier > 0 && ! ( mod & core . Qt__ShiftModifier > 0 ) {
text = strings . ToLower ( string ( rune ( key ) ) )
2020-05-30 20:39:21 +09:00
}
}
2018-01-05 08:07:29 +00:00
if mod & core . Qt__KeypadModifier > 0 {
switch core . Qt__Key ( key ) {
case core . Qt__Key_Home :
2022-04-02 14:31:56 +09:00
return fmt . Sprintf ( "<%skHome>" , e . modPrefix ( mod ) )
2018-01-05 08:07:29 +00:00
case core . Qt__Key_End :
2022-04-02 14:31:56 +09:00
return fmt . Sprintf ( "<%skEnd>" , e . modPrefix ( mod ) )
2018-01-05 08:07:29 +00:00
case core . Qt__Key_PageUp :
2022-04-02 14:31:56 +09:00
return fmt . Sprintf ( "<%skPageUp>" , e . modPrefix ( mod ) )
2018-01-05 08:07:29 +00:00
case core . Qt__Key_PageDown :
2022-04-02 14:31:56 +09:00
return fmt . Sprintf ( "<%skPageDown>" , e . modPrefix ( mod ) )
2018-01-05 08:07:29 +00:00
case core . Qt__Key_Plus :
2020-11-10 23:21:20 +09:00
return fmt . Sprintf ( "<%skPlus>" , e . modPrefix ( mod ) )
2018-01-05 08:07:29 +00:00
case core . Qt__Key_Minus :
2020-11-10 23:21:20 +09:00
return fmt . Sprintf ( "<%skMinus>" , e . modPrefix ( mod ) )
2018-01-05 08:07:29 +00:00
case core . Qt__Key_multiply :
2020-11-10 23:21:20 +09:00
return fmt . Sprintf ( "<%skMultiply>" , e . modPrefix ( mod ) )
2018-01-05 08:07:29 +00:00
case core . Qt__Key_division :
2020-11-10 23:21:20 +09:00
return fmt . Sprintf ( "<%skDivide>" , e . modPrefix ( mod ) )
2018-01-05 08:07:29 +00:00
case core . Qt__Key_Enter :
2020-11-10 23:21:20 +09:00
return fmt . Sprintf ( "<%skEnter>" , e . modPrefix ( mod ) )
2018-01-05 08:07:29 +00:00
case core . Qt__Key_Period :
2020-11-10 23:21:20 +09:00
return fmt . Sprintf ( "<%skPoint>" , e . modPrefix ( mod ) )
case core . Qt__Key_0 :
return fmt . Sprintf ( "<%sk0>" , e . modPrefix ( mod ) )
case core . Qt__Key_1 :
return fmt . Sprintf ( "<%sk1>" , e . modPrefix ( mod ) )
case core . Qt__Key_2 :
return fmt . Sprintf ( "<%sk2>" , e . modPrefix ( mod ) )
case core . Qt__Key_3 :
return fmt . Sprintf ( "<%sk3>" , e . modPrefix ( mod ) )
case core . Qt__Key_4 :
return fmt . Sprintf ( "<%sk4>" , e . modPrefix ( mod ) )
case core . Qt__Key_5 :
return fmt . Sprintf ( "<%sk5>" , e . modPrefix ( mod ) )
case core . Qt__Key_6 :
return fmt . Sprintf ( "<%sk6>" , e . modPrefix ( mod ) )
case core . Qt__Key_7 :
return fmt . Sprintf ( "<%sk7>" , e . modPrefix ( mod ) )
case core . Qt__Key_8 :
return fmt . Sprintf ( "<%sk8>" , e . modPrefix ( mod ) )
case core . Qt__Key_9 :
return fmt . Sprintf ( "<%sk9>" , e . modPrefix ( mod ) )
2018-01-05 08:07:29 +00:00
}
}
2017-06-16 08:43:05 +01:00
2021-07-25 22:35:17 +09:00
specialKey , ok := e . specialKeys [ core . Qt__Key ( key ) ]
if ok {
if key == int ( core . Qt__Key_Space ) || key == int ( core . Qt__Key_Backspace ) {
mod &= ^ core . Qt__ShiftModifier
}
return fmt . Sprintf ( "<%s%s>" , e . modPrefix ( mod ) , specialKey )
}
2018-01-05 08:07:29 +00:00
if text == "<" {
2020-03-24 23:40:45 +09:00
modNoShift := mod & ^ core . Qt__ShiftModifier
return fmt . Sprintf ( "<%s%s>" , e . modPrefix ( modNoShift ) , "lt" )
2017-06-06 02:42:11 +01:00
}
2021-07-25 22:35:17 +09:00
isCaretKey := key == int ( core . Qt__Key_6 ) || key == int ( core . Qt__Key_AsciiCircum )
// Normalize modifiers, CTRL+^ always sends as <C-^>
2021-07-30 12:01:15 +09:00
if isCaretKey && ( mod & controlModifier ( ) > 0 ) {
2021-07-25 22:35:17 +09:00
modNoShiftMeta := mod & ^ core . Qt__ShiftModifier & ^ cmdModifier ( )
return fmt . Sprintf ( "<%s%s>" , e . modPrefix ( modNoShiftMeta ) , "^" )
2018-01-05 08:07:29 +00:00
}
2017-06-16 08:43:05 +01:00
2020-03-22 22:51:13 +09:00
if text == "\\" {
2018-01-05 08:07:29 +00:00
return fmt . Sprintf ( "<%s%s>" , e . modPrefix ( mod ) , "Bslash" )
}
2017-06-16 08:43:05 +01:00
2021-07-25 22:35:17 +09:00
rtext := [ ] rune ( text )
isGraphic := false
if len ( rtext ) > 0 {
isGraphic = unicode . IsGraphic ( rtext [ 0 ] )
}
if text == "" || ! isGraphic {
2020-11-28 09:21:42 +09:00
if key == int ( core . Qt__Key_Alt ) ||
key == int ( core . Qt__Key_AltGr ) ||
key == int ( core . Qt__Key_CapsLock ) ||
key == int ( core . Qt__Key_Control ) ||
key == int ( core . Qt__Key_Meta ) ||
key == int ( core . Qt__Key_Shift ) ||
key == int ( core . Qt__Key_Super_L ) ||
key == int ( core . Qt__Key_Super_R ) {
2018-01-05 08:07:29 +00:00
return ""
2017-06-06 02:42:11 +01:00
}
2021-07-25 22:35:17 +09:00
// Ignore special keys
if key == int ( core . Qt__Key_VolumeDown ) ||
2021-07-30 12:01:15 +09:00
key == int ( core . Qt__Key_VolumeMute ) ||
key == int ( core . Qt__Key_VolumeUp ) {
2021-07-25 22:35:17 +09:00
return ""
2020-03-24 00:03:42 +09:00
}
2021-07-30 12:01:15 +09:00
2021-07-25 22:35:17 +09:00
text = keyToText ( key , mod )
2020-03-24 00:03:42 +09:00
}
2021-07-30 12:01:15 +09:00
c := text
2020-03-24 00:03:42 +09:00
if c == "" {
return ""
2018-01-05 08:07:29 +00:00
}
2020-03-22 22:51:13 +09:00
2021-10-15 21:20:19 +09:00
char := [ ] rune ( c ) [ 0 ]
// char := core.NewQChar11(c)
2020-03-22 22:51:13 +09:00
// Remove SHIFT
2021-10-15 21:20:19 +09:00
if ( int ( char ) >= 0x80 || unicode . IsPrint ( char ) ) && ! ( mod & controlModifier ( ) > 0 ) && ! ( mod & cmdModifier ( ) > 0 ) {
2020-03-24 00:03:42 +09:00
mod &= ^ core . Qt__ShiftModifier
2019-10-31 23:06:47 +09:00
}
2021-10-15 21:20:19 +09:00
// if (char.Unicode() >= 0x80 || char.IsPrint()) && !(mod&controlModifier() > 0) && !(mod&cmdModifier() > 0) {
// mod &= ^core.Qt__ShiftModifier
// }
2019-10-31 23:06:47 +09:00
2020-03-22 22:51:13 +09:00
// Remove CTRL
2021-10-15 21:20:19 +09:00
if int ( char ) < 0x20 {
2021-07-25 22:35:17 +09:00
text = keyToText ( key , mod )
2018-01-05 08:07:29 +00:00
}
2021-10-15 21:20:19 +09:00
// if char.Unicode() < 0x20 {
// text = keyToText(key, mod)
// }
2017-06-13 16:15:05 +01:00
2020-03-24 23:40:45 +09:00
if runtime . GOOS == "darwin" {
2020-03-22 22:51:13 +09:00
// Remove ALT/OPTION
2021-10-15 21:20:19 +09:00
if int ( char ) >= 0x80 && unicode . IsPrint ( char ) {
2020-03-24 00:03:42 +09:00
mod &= ^ core . Qt__AltModifier
2020-03-22 22:51:13 +09:00
}
2021-10-15 21:20:19 +09:00
// if char.Unicode() >= 0x80 && char.IsPrint() {
// mod &= ^core.Qt__AltModifier
// }
2021-07-30 12:01:15 +09:00
// Some locales require Alt for basic low-ascii characters,
// remove AltModifer. Ex) German layouts use Alt for "{".
if isAsciiCharRequiringAlt ( key , mod , [ ] rune ( c ) [ 0 ] ) {
mod &= ^ core . Qt__AltModifier
}
2017-07-03 07:14:29 +01:00
}
2018-01-05 08:07:29 +00:00
prefix := e . modPrefix ( mod )
if prefix != "" {
return fmt . Sprintf ( "<%s%s>" , prefix , c )
}
return c
}
func ( e * Editor ) modPrefix ( mod core . Qt__KeyboardModifier ) string {
prefix := ""
2020-03-24 00:03:42 +09:00
if runtime . GOOS == "windows" {
2021-07-25 22:35:17 +09:00
if mod & controlModifier ( ) > 0 && ! ( mod & core . Qt__AltModifier > 0 ) {
2020-03-24 00:03:42 +09:00
prefix += "C-"
}
if mod & core . Qt__ShiftModifier > 0 {
prefix += "S-"
}
2021-07-25 22:35:17 +09:00
if mod & core . Qt__AltModifier > 0 && ! ( mod & controlModifier ( ) > 0 ) {
2020-03-24 00:03:42 +09:00
prefix += e . prefixToMapMetaKey
}
} else {
2021-07-25 22:35:17 +09:00
if mod & cmdModifier ( ) > 0 {
2018-01-05 08:07:29 +00:00
prefix += "D-"
2017-07-03 07:14:29 +01:00
}
2021-07-25 22:35:17 +09:00
if mod & controlModifier ( ) > 0 {
2020-03-22 22:51:13 +09:00
prefix += "C-"
}
2020-03-24 00:03:42 +09:00
if mod & core . Qt__ShiftModifier > 0 {
prefix += "S-"
}
if mod & core . Qt__AltModifier > 0 {
2020-03-22 23:21:40 +09:00
prefix += e . prefixToMapMetaKey
2020-03-22 22:51:13 +09:00
}
2018-01-05 08:07:29 +00:00
}
return prefix
}
func ( e * Editor ) initSpecialKeys ( ) {
e . specialKeys = map [ core . Qt__Key ] string { }
e . specialKeys [ core . Qt__Key_Up ] = "Up"
e . specialKeys [ core . Qt__Key_Down ] = "Down"
e . specialKeys [ core . Qt__Key_Left ] = "Left"
e . specialKeys [ core . Qt__Key_Right ] = "Right"
e . specialKeys [ core . Qt__Key_F1 ] = "F1"
e . specialKeys [ core . Qt__Key_F2 ] = "F2"
e . specialKeys [ core . Qt__Key_F3 ] = "F3"
e . specialKeys [ core . Qt__Key_F4 ] = "F4"
e . specialKeys [ core . Qt__Key_F5 ] = "F5"
e . specialKeys [ core . Qt__Key_F6 ] = "F6"
e . specialKeys [ core . Qt__Key_F7 ] = "F7"
e . specialKeys [ core . Qt__Key_F8 ] = "F8"
e . specialKeys [ core . Qt__Key_F9 ] = "F9"
e . specialKeys [ core . Qt__Key_F10 ] = "F10"
e . specialKeys [ core . Qt__Key_F11 ] = "F11"
e . specialKeys [ core . Qt__Key_F12 ] = "F12"
e . specialKeys [ core . Qt__Key_F13 ] = "F13"
e . specialKeys [ core . Qt__Key_F14 ] = "F14"
e . specialKeys [ core . Qt__Key_F15 ] = "F15"
e . specialKeys [ core . Qt__Key_F16 ] = "F16"
e . specialKeys [ core . Qt__Key_F17 ] = "F17"
e . specialKeys [ core . Qt__Key_F18 ] = "F18"
e . specialKeys [ core . Qt__Key_F19 ] = "F19"
e . specialKeys [ core . Qt__Key_F20 ] = "F20"
e . specialKeys [ core . Qt__Key_F21 ] = "F21"
e . specialKeys [ core . Qt__Key_F22 ] = "F22"
e . specialKeys [ core . Qt__Key_F23 ] = "F23"
e . specialKeys [ core . Qt__Key_F24 ] = "F24"
e . specialKeys [ core . Qt__Key_Backspace ] = "BS"
2020-11-28 09:21:42 +09:00
e . specialKeys [ core . Qt__Key_Delete ] = "Del"
e . specialKeys [ core . Qt__Key_Insert ] = "Insert"
e . specialKeys [ core . Qt__Key_Home ] = "Home"
e . specialKeys [ core . Qt__Key_End ] = "End"
e . specialKeys [ core . Qt__Key_PageUp ] = "PageUp"
e . specialKeys [ core . Qt__Key_PageDown ] = "PageDown"
e . specialKeys [ core . Qt__Key_Return ] = "Enter"
e . specialKeys [ core . Qt__Key_Enter ] = "Enter"
e . specialKeys [ core . Qt__Key_Tab ] = "Tab"
e . specialKeys [ core . Qt__Key_Backtab ] = "Tab"
e . specialKeys [ core . Qt__Key_Escape ] = "Esc"
2018-01-05 08:07:29 +00:00
e . specialKeys [ core . Qt__Key_Backslash ] = "Bslash"
2020-11-28 09:21:42 +09:00
e . specialKeys [ core . Qt__Key_Space ] = "Space"
2018-01-05 08:07:29 +00:00
2020-03-24 00:03:42 +09:00
if runtime . GOOS == "darwin" {
2018-01-05 08:07:29 +00:00
e . keyControl = core . Qt__Key_Meta
e . keyCmd = core . Qt__Key_Control
2020-03-24 00:03:42 +09:00
} else if runtime . GOOS == "windows" {
e . keyControl = core . Qt__Key_Control
e . keyCmd = ( core . Qt__Key ) ( 0 )
2018-01-05 08:07:29 +00:00
} else {
e . keyControl = core . Qt__Key_Control
2020-03-24 00:03:42 +09:00
e . keyCmd = core . Qt__Key_Meta
2018-01-05 08:07:29 +00:00
}
2020-03-24 23:40:45 +09:00
e . prefixToMapMetaKey = "A-"
2017-06-06 02:42:11 +01:00
}
2018-01-08 10:23:16 +00:00
2022-03-01 14:30:47 +09:00
func ( e * Editor ) close ( exitcode int ) {
2018-01-08 10:23:16 +00:00
e . stopOnce . Do ( func ( ) {
2022-03-01 14:30:47 +09:00
e . stop <- exitcode
2018-01-08 10:23:16 +00:00
} )
}
2022-02-11 11:53:54 +09:00
func ( e * Editor ) saveAppWindowState ( ) {
settings := core . NewQSettings ( "neovim" , "goneovim" , nil )
settings . SetValue ( "geometry" , core . NewQVariant13 ( e . window . SaveGeometry ( ) ) )
settings . SetValue ( "windowState" , core . NewQVariant13 ( e . window . SaveState ( 0 ) ) )
}
2018-01-08 10:23:16 +00:00
func ( e * Editor ) cleanup ( ) {
2020-10-01 00:11:46 +09:00
sessions := filepath . Join ( e . configDir , "sessions" )
2018-01-08 10:23:16 +00:00
os . RemoveAll ( sessions )
os . MkdirAll ( sessions , 0755 )
2018-01-11 06:11:34 +00:00
select {
case <- e . stop :
return
default :
}
2018-01-08 10:23:16 +00:00
for i , ws := range e . workspaces {
sessionPath := filepath . Join ( sessions , strconv . Itoa ( i ) + ".vim" )
fmt . Println ( sessionPath )
fmt . Println ( ws . nvim . Command ( "mksession " + sessionPath ) )
fmt . Println ( "mksession finished" )
}
}