From 8875f99279308bcc87f4b713c083e58c45026132 Mon Sep 17 00:00:00 2001 From: Paul Wilde Date: Sat, 16 Jul 2022 14:20:55 +0100 Subject: [PATCH] added clip_wl - clipboard manager for wayland --- base.nim | 18 ++++++-- clip_wl.nim | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++ notes.nim | 2 +- remmina.nim | 9 ++++ 4 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 clip_wl.nim diff --git a/base.nim b/base.nim index 5e43cdd..2ddccc3 100644 --- a/base.nim +++ b/base.nim @@ -34,6 +34,7 @@ type x*: int y*: int +const WM_TOOLS_DIR* = getHomeDir() & "Nextcloud/.wm_tools/" const background* = "#000000" const backgroundalt* = "#bb222222" const backgroundalt2* = "#bb333333" @@ -136,8 +137,10 @@ proc debugLog*(str: string) = proc switchTwmMode*(mode: string = "default") = # I intend to add support for more twm as time goes on (I switch around a lot) # Switch out of an i3 bindsym mode if set - discard execCmd("sway mode \"" & mode & "\"") - discard execCmd("i3-msg mode \"" & mode & "\"") + if wayland: + discard execCmd("sway mode \"" & mode & "\"") + else: + discard execCmd("i3-msg mode \"" & mode & "\"") proc checkWayland() = if getEnv("XDG_SESSION_TYPE") == "wayland": @@ -216,7 +219,10 @@ proc runMenu*(data: Info, opts: varargs[string], rofi: bool = false): string = return output.output proc copyToClipboard*(str: string) = - discard execCmd("echo -n " & quote(str) & " | xclip -selection clipboard") + if wayland: + discard execCmd("wl-copy " & str) + else: + discard execCmd("echo -n " & quote(str) & " | xclip -selection clipboard") proc outputData*(data: Info, args: varargs[string]): string {.discardable.} = var output = "" @@ -234,13 +240,17 @@ proc outputData*(data: Info, args: varargs[string]): string {.discardable.} = return output +proc checkCacheDir() = + if not dirExists(WM_TOOLS_DIR): + createDir(WM_TOOLS_DIR) # At Start up: +checkCacheDir() +checkWayland() # Switch bindsym mode back to default as it could be being used. switchTwmMode() -checkWayland() let args* = getArguments() for idx, arg in args: diff --git a/clip_wl.nim b/clip_wl.nim new file mode 100644 index 0000000..af82554 --- /dev/null +++ b/clip_wl.nim @@ -0,0 +1,116 @@ +import base +import std/[strutils,os,db_sqlite,osproc] + +const CLIP_DB = WM_TOOLS_DIR & ".clipboard_cache.sqlite" +const KEEP_ITEMS = 20 + +proc openDBConn(): DBConn = + let db: DBconn = open(CLIP_DB,"","","") + try: + db.exec(sql"""create table if not exists + clip_items ( + timestamp DATETIME NOT NULL, + clip NVARCHAR(500) NOT NULL + ) + """) + except: + echo getCurrentExceptionMsg() + return db + +proc clearHistory() = + let db = openDBConn() + defer: db.close() + try: + db.exec(sql"drop table if exists clip_items") + except: + echo getCurrentExceptionMsg() + +proc getCurrentClipboardContent(): string = + var str = "" + if wayland: + let cur = execCmdEx("wl-paste") + if cur.exitcode == 0: + str = cur[0] + else: + echo cur + return str + +proc maintainDB() = + let db = openDBConn() + try: + db.exec(sql"""BEGIN""") + db.exec(sql"delete from clip_items order by timestamp desc offset ?", KEEP_ITEMS) + db.exec(sql"""COMMIT""") + except: + echo getCurrentExceptionMsg() + +proc escapeClip(str: string): string = + var clip = str + clip = clip.replace("`","\\`") + clip = escape(clip) + return clip + +proc unescapeClip(str: string): string = + var clip = str + try: + clip = unescape(clip) + except: + echo getCurrentExceptionMsg() + + return clip + +proc readClipFile(): seq[string] = + var clips: seq[string] = @[] + let db = openDBConn() + defer: db.close() + try: + for row in db.fastRows(sql"select clip from clip_items order by timestamp desc"): + var str = unescapeClip(row[0]) + clips.add(str) + except: + echo getCurrentExceptionMsg() + return clips + +proc addClip(str: string) = + if str == "": + return + let db = openDBConn() + defer: db.close() + try: + db.exec(sql"""BEGIN""") + db.exec(sql"""insert into clip_items (timestamp, clip) + values (CURRENT_TIMESTAMP, ?) + """, escapeClip(str)) + db.exec(sql"""COMMIT""") + except: + echo getCurrentExceptionMsg() + return + +proc showClips() = + let clips = readClipFile() + let info = newInfo("Clips") + let option = outputData(info, clips) + if option != "": + copyToClipboard(option) + return + +proc main() = + for idx, arg in args: + if arg == "set": + addClip(getCurrentClipboardContent()) + return + if arg == "clear": + clearHistory() + return + showClips() + return + +block start: + if isMainModule: + if not wayland: + echo "Not a wayland session, exiting..." + break start + else: + main() + +maintainDB() diff --git a/notes.nim b/notes.nim index 76b2aec..1b8393e 100644 --- a/notes.nim +++ b/notes.nim @@ -1,7 +1,7 @@ import base import std/[os,strutils,sequtils,times] -const note_dir = getHomeDir() & "Nextcloud/.notes.dmenu/" # Putting it in Nextcloud so it can sync :-) +const note_dir = WM_TOOLS_DIR & ".notes.dmenu/" # Putting it in Nextcloud so it can sync :-) const default_bg = white const default_fg = black diff --git a/remmina.nim b/remmina.nim index a4f837a..344ecc4 100644 --- a/remmina.nim +++ b/remmina.nim @@ -3,12 +3,18 @@ import std/[os,osproc,tables,algorithm] import configparser const REMMINA_DIR = getHomeDir() & ".local/share/remmina" +const REMMINA_WS = "4" var sessions = initTable[string,string]() var names: seq[string] = @[] proc main() +proc switchWorkspace() = + if REMMINA_WS != "": + discard execCmd("i3-msg workspace number " & REMMINA_WS) + discard execCmd("swaymsg workspace number " & REMMINA_WS) + proc getRemminaFiles(): seq[string] = if len(names) < 1: for file in walkFiles(REMMINA_DIR & "/*.remmina"): @@ -40,12 +46,15 @@ proc selectRemmina(conn: string) = case output: of "connect": startRemmina(conn) + switchWorkspace() of "edit": editRemmina(conn) + switchWorkspace() of "back": main() + proc main() = var info = newInfo("Remmina") var args: seq[string] = getRemminaFiles()