summaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2025-08-10 17:24:44 +0800
committerlittleblack111 <littleblack11111@gmail.com>2025-08-10 17:24:44 +0800
commitab8535cc578672f844419d25fc1cc8e8790f1aa8 (patch)
tree756609ca8202815e42d924c010a43e6ea44a23be /services
parenta9da23c79d9a6ef963bb153afcf9707753cbded9 (diff)
interal(query): move to Searchable module
from https://github.com/caelestia-dots/shell license is GPL, this project don't have a license yet, will use GPL
Diffstat (limited to 'services')
-rw-r--r--services/AppSearch.qml65
-rw-r--r--services/Clip.qml58
2 files changed, 15 insertions, 108 deletions
diff --git a/services/AppSearch.qml b/services/AppSearch.qml
index 9cd10d4..8063e0f 100644
--- a/services/AppSearch.qml
+++ b/services/AppSearch.qml
@@ -1,18 +1,16 @@
pragma Singleton
-import "../utils/levendist.js" as Levendist
import Quickshell
import Quickshell.Io
import qs.config
+import qs.components
-/**
- * - Eases fuzzy searching for applications by name
- * - Guesses icon name for window class name
- */
-Singleton {
+Searchable {
id: root
- property int scoreThreshold: General.appSearchFuzzySearchThreshold
+ list: Array.from(DesktopEntries.applications.values).sort((a, b) => a.name.localeCompare(b.name))
+ scoreThreshold: General.appSearchFuzzySearchThreshold
+ algorithm: Searchable.SearchAlgorithm.Levendist
property var substitutions: ({
"code-url-handler": "visual-studio-code",
@@ -45,60 +43,9 @@ Singleton {
}
]
- property var fuzzyQueryCache: ({})
property var iconExistsCache: ({})
property var guessIconCache: ({})
- readonly property list<DesktopEntry> list: Array.from(DesktopEntries.applications.values).sort((a, b) => a.name.localeCompare(b.name))
-
- /**
- * Returns an Array<DesktopEntry> for a given search.
- * Results are cached by exact search string and, if the
- * search starts with a previously cached key, uses that
- * cached result as the source for filtering.
- */
- function fuzzyQuery(search) { // search is expected to be .toLowerCase()
- if (root.fuzzyQueryCache[search]) {
- return root.fuzzyQueryCache[search];
- }
-
- let source = list;
- let previousLists = Object.keys(root.fuzzyQueryCache).filter(key => key && search.startsWith(key));
- if (previousLists.length > 0) {
- var longest = previousLists.reduce((a, b) => a.length >= b.length ? a : b);
- source = root.fuzzyQueryCache[longest];
- }
-
- const p = [], f = [];
- for (const s of source) {
- const t = s.name.toLowerCase();
- if (t.startsWith(search)) {
- p.push(s);
- continue;
- }
- let pos = 0;
- for (const c of search) {
- pos = t.indexOf(c, pos);
- if (pos < 0) {
- pos = 0;
- break;
- }
- pos++;
- }
- if (pos)
- f.push({
- s,
- score: Levendist.distance(search, t)
- });
- }
- const results = p.concat(f.sort((a, b) => a.score - b.score).map(({
- s
- }) => s));
-
- root.fuzzyQueryCache[search] = results;
- return results;
- }
-
function iconExists(iconName) {
if (!iconName || iconName.length === 0) {
return false;
@@ -157,7 +104,7 @@ Singleton {
}
if (!result) {
- const matches = root.fuzzyQuery(str);
+ const matches = root.query(str);
if (matches.length > 0) {
const candidate = matches[0].icon;
if (root.iconExists(candidate)) {
diff --git a/services/Clip.qml b/services/Clip.qml
index 6fee97c..81fea60 100644
--- a/services/Clip.qml
+++ b/services/Clip.qml
@@ -3,11 +3,14 @@ pragma Singleton
import Quickshell
import Quickshell.Io
import QtQuick
-import "../utils/levendist.js" as Levendist
+import qs.components
-Singleton {
+Searchable {
id: root
+ key: "data"
+ algorithm: Searchable.SearchAlgorithm.Levendist
+
property list<string> _clipHist: []
property list<string> _clipImg: []
property list<string> _clipImgIds: _clipImg.map(p => p.split("/").pop().split(".").shift())
@@ -16,9 +19,7 @@ Singleton {
property string toCopy: ""
property string decoded: ""
- property var fuzzyQueryCache: ({});
-
- property var clipHist: {
+ list: {
const arr = [];
if (!_clipHist?.length)
return arr;
@@ -42,7 +43,7 @@ Singleton {
const n = parseInt(raw.slice(0, tab), 10);
if (!Number.isNaN(n)) {
idNum = n;
- payload = raw.slice(tab + 1); // strip "ID<TAB>"
+ payload = raw.slice(tab + 1);
}
}
@@ -60,49 +61,8 @@ Singleton {
return arr;
}
- function fuzzyQuery(search) {
- if (!search)
- return root.clipHist;
- if (root.fuzzyQueryCache[search]) {
- return root.fuzzyQueryCache[search];
- }
- let source = root.clipHist;
- let previousLists = Object.keys(root.fuzzyQueryCache).filter(key => key && search.startsWith(key));
- if (previousLists.length > 0) {
- var longest = previousLists.reduce((a, b) => a.length >= b.length ? a : b);
- source = root.fuzzyQueryCache[longest];
- }
- const p = [], f = [];
- for (const s of source) {
- const t = (s.isImage ? "image" : (s.data || "")).toLowerCase();
- if (t.startsWith(search)) {
- p.push(s);
- continue;
- }
- let pos = 0;
- for (const c of search) {
- pos = t.indexOf(c, pos);
- if (pos < 0) {
- pos = 0;
- break;
- }
- pos++;
- }
- if (pos)
- f.push({
- s,
- score: Levendist.distance(search, t)
- });
- }
- const results = p.concat(f.sort((a, b) => a.score - b.score).map(({s}) => s));
- root.fuzzyQueryCache[search] = results;
- return results;
- }
-
- component SClip_t: QtObject {
- property int index
- property bool isImage
- property string data
+ function transformSearch(search: string): string {
+ return search.toLowerCase();
}
function decodeAndCopy(text) {