1
Fork 0
mirror of https://github.com/j1g5awi/krunner-vscode.git synced 2024-11-22 21:09:29 +00:00
krunner-vscode/krunner_vscode/__main__.py

133 lines
3.2 KiB
Python
Raw Normal View History

2023-05-14 17:57:22 +01:00
import difflib
2022-03-25 12:04:29 +00:00
import json
import os
import sqlite3
2023-05-14 18:00:35 +01:00
import sys
from operator import attrgetter
2022-04-09 16:42:40 +01:00
from pathlib import Path
2022-03-25 12:04:29 +00:00
from typing import NamedTuple
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
from gi.repository import GLib
DBusGMainLoop(set_as_default=True)
objpath = "/vscode"
iface = "org.kde.krunner1"
VSCODE_DIRS = [
"Code",
"Code - OSS",
"VSCodium"
]
2022-03-25 12:04:29 +00:00
class Match(NamedTuple):
data: str
display_text: str
icon: str
type: int
relevance: float
properties: dict
2023-05-14 17:57:22 +01:00
def get_matches(paths, query):
"""
Equivalent to `difflib.get_close_matches`, but returning the ratio too
"""
matches = []
s = difflib.SequenceMatcher()
s.set_seq2(query)
for path in paths:
s.set_seq1(path)
matches.append((s.ratio(), path))
return matches
2022-03-25 12:04:29 +00:00
# Read path_list from database
2022-03-28 09:36:38 +01:00
def get_path_list():
2023-05-07 17:38:10 +01:00
paths = set()
for vscode_dir in VSCODE_DIRS:
state_file = os.path.join(
os.environ["HOME"], ".config", vscode_dir, "User/globalStorage/state.vscdb"
)
if not os.path.exists(state_file):
continue
con = sqlite3.connect(state_file)
cur = con.cursor()
rows = cur.execute(
"SELECT value FROM ItemTable WHERE key = 'history.recentlyOpenedPathsList'"
)
data = json.loads(rows.fetchone()[0])
con.close()
paths.update(
{
"~" + path[len(os.environ["HOME"]) :] if os.environ["HOME"] in path else path
for path in [i["folderUri"][7:] for i in data["entries"] if "folderUri" in i]
}
2022-03-28 09:36:38 +01:00
)
2023-05-07 17:38:10 +01:00
return paths
2022-03-25 12:04:29 +00:00
class Runner(dbus.service.Object):
def __init__(self):
dbus.service.Object.__init__(
self,
dbus.service.BusName(
"com.github.j1g5awi.vscode", dbus.SessionBus() # type:ignore
),
objpath,
)
@dbus.service.method(iface, in_signature="s", out_signature="a(sssida{sv})")
def Match(self, query: str):
# data, display text, icon, type (Plasma::QueryType), relevance (0-1), properties (subtext, category and urls)
2023-05-14 17:57:22 +01:00
matches = get_matches(get_path_list(), query)
2022-03-25 12:04:29 +00:00
return [
Match(
path,
2022-04-09 16:42:40 +01:00
Path(path).name,
2022-03-25 12:04:29 +00:00
"com.visualstudio.code.oss",
100,
2023-05-14 17:57:22 +01:00
ratio,
2022-03-25 12:04:29 +00:00
{"subtext": path},
)
2023-05-14 17:57:22 +01:00
for ratio, path in matches
2022-03-25 12:04:29 +00:00
]
@dbus.service.method(iface, out_signature="a(sss)")
def Actions(self):
# id, text, icon
return [("id", "Open Folder", "document-open-folder")]
@dbus.service.method(iface, in_signature="ss")
def Run(self, data: str, action_id: str):
if not action_id:
os.system("code " + data)
else:
os.system("xdg-open " + data)
2023-05-14 18:00:35 +01:00
def main():
runner = Runner()
if sys.argv[1:]:
# Manual search - useful for local testing
for match in sorted(runner.Match(sys.argv[1]), key=attrgetter("relevance")):
print(match.data, match.relevance)
else:
loop = GLib.MainLoop()
loop.run()
if __name__ == "__main__":
main()