diff --git a/.config/quickshell/ii/modules/common/widgets/CliphistImage.qml b/.config/quickshell/ii/modules/common/widgets/CliphistImage.qml
index ce15ef3ea..e72954622 100644
--- a/.config/quickshell/ii/modules/common/widgets/CliphistImage.qml
+++ b/.config/quickshell/ii/modules/common/widgets/CliphistImage.qml
@@ -53,7 +53,7 @@ Rectangle {
Process {
id: decodeImageProcess
command: ["bash", "-c",
- `[ -f ${imageDecodeFilePath} ] || echo '${StringUtils.shellSingleQuoteEscape(root.entry)}' | cliphist decode > '${imageDecodeFilePath}'`
+ `[ -f ${imageDecodeFilePath} ] || echo '${StringUtils.shellSingleQuoteEscape(root.entry)}' | ${Cliphist.cliphistBinary} decode > '${imageDecodeFilePath}'`
]
onExited: (exitCode, exitStatus) => {
if (exitCode === 0) {
diff --git a/.config/quickshell/ii/modules/overview/SearchItem.qml b/.config/quickshell/ii/modules/overview/SearchItem.qml
index 921fc8b6d..ebbfb090c 100644
--- a/.config/quickshell/ii/modules/overview/SearchItem.qml
+++ b/.config/quickshell/ii/modules/overview/SearchItem.qml
@@ -1,5 +1,6 @@
// pragma NativeMethodBehavior: AcceptThisObject
import qs
+import qs.services
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.functions
@@ -89,8 +90,8 @@ RippleButton {
}
onClicked: {
- root.itemExecute()
GlobalStates.overviewOpen = false
+ root.itemExecute()
}
Keys.onPressed: (event) => {
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
@@ -201,7 +202,7 @@ RippleButton {
}
}
Loader { // Clipboard image preview
- active: root.cliphistRawString && /^\d+\t\[\[.*binary data.*\d+x\d+.*\]\]$/.test(root.cliphistRawString)
+ active: root.cliphistRawString && Cliphist.entryIsImage(root.cliphistRawString)
sourceComponent: CliphistImage {
Layout.fillWidth: true
entry: root.cliphistRawString
diff --git a/.config/quickshell/ii/modules/overview/SearchWidget.qml b/.config/quickshell/ii/modules/overview/SearchWidget.qml
index fe45f9702..78a1b46b7 100644
--- a/.config/quickshell/ii/modules/overview/SearchWidget.qml
+++ b/.config/quickshell/ii/modules/overview/SearchWidget.qml
@@ -37,12 +37,24 @@ Item { // Wrapper
}
property var searchActions: [
+ {
+ action: "accentcolor",
+ execute: args => {
+ Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--noswitch", "--color", ...(args != '' ? [`${args}`] : [])]);
+ }
+ },
{
action: "dark",
execute: () => {
Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--mode", "dark", "--noswitch"]);
}
},
+ {
+ action: "konachanwallpaper",
+ execute: () => {
+ Quickshell.execDetached([Quickshell.shellPath("scripts/colors/random_konachan_wall.sh")]);
+ }
+ },
{
action: "light",
execute: () => {
@@ -50,21 +62,21 @@ Item { // Wrapper
}
},
{
- action: "wall",
- execute: () => {
- Quickshell.execDetached([Directories.wallpaperSwitchScriptPath]);
- }
- },
- {
- action: "konachanwall",
- execute: () => {
- Quickshell.execDetached([Quickshell.shellPath("scripts/colors/random_konachan_wall.sh")]);
- }
- },
- {
- action: "accentcolor",
+ action: "superpaste",
execute: args => {
- Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--noswitch", "--color", ...(args != '' ? [`${args}`] : [])]);
+ if (!/^(\d+)/.test(args.trim())) { // Invalid if doesn't start with numbers
+ Quickshell.execDetached([
+ "notify-send",
+ Translation.tr("Superpaste"),
+ Translation.tr("Usage: %1superpaste NUM_OF_ENTRIES[i]\nSupply i when you want images\nExamples:\n%1superpaste 4i for the last 4 images\n%1superpaste 7 for the last 7 entries").arg(Config.options.search.prefix.action),
+ "-a", "Shell"
+ ]);
+ return;
+ }
+ const syntaxMatch = /^(?:(\d+)(i)?)/.exec(args.trim());
+ const count = syntaxMatch[1] ? parseInt(syntaxMatch[1]) : 1;
+ const isImage = !!syntaxMatch[2];
+ Cliphist.superpaste(count, isImage);
}
},
{
@@ -73,6 +85,12 @@ Item { // Wrapper
Todo.addTask(args);
}
},
+ {
+ action: "wallpaper",
+ execute: () => {
+ GlobalStates.wallpaperSelectorOpen = true;
+ }
+ },
]
function focusFirstItem() {
diff --git a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml
index e3056b57d..22a64412c 100644
--- a/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml
+++ b/.config/quickshell/ii/modules/sidebarLeft/AiChat.qml
@@ -219,7 +219,7 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\)
function handleEntry(entry: string) {
imageDecodeFileName = parseInt(entry.match(/^(\d+)\t/)[1])
decodeImageAndAttachProc.exec(["bash", "-c",
- `[ -f ${imageDecodeFilePath} ] || echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode > '${imageDecodeFilePath}'`
+ `[ -f ${imageDecodeFilePath} ] || echo '${StringUtils.shellSingleQuoteEscape(entry)}' | ${Cliphist.cliphistBinary} decode > '${imageDecodeFilePath}'`
])
}
onExited: (exitCode, exitStatus) => {
diff --git a/.config/quickshell/ii/services/Cliphist.qml b/.config/quickshell/ii/services/Cliphist.qml
index 3bd9cbc00..32b2a0203 100644
--- a/.config/quickshell/ii/services/Cliphist.qml
+++ b/.config/quickshell/ii/services/Cliphist.qml
@@ -9,6 +9,10 @@ import Quickshell.Io
Singleton {
id: root
+ // property string cliphistBinary: FileUtils.trimFileProtocol(`${Directories.home}/.cargo/bin/stash`)
+ property string cliphistBinary: "cliphist"
+ property real pasteDelay: 0.05
+ property string pressPasteCommand: "ydotool key -d 1 29:1 47:1 47:0 29:0"
property bool sloppySearch: Config.options?.search.sloppy ?? false
property real scoreThreshold: 0.2
property list entries: []
@@ -35,19 +39,48 @@ Singleton {
});
}
+ function entryIsImage(entry) {
+ return !!(/^\d+\t\[\[.*binary data.*\d+x\d+.*\]\]$/.test(entry))
+ }
+
function refresh() {
readProc.buffer = []
readProc.running = true
}
function copy(entry) {
- Quickshell.execDetached(["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(entry)}' | cliphist decode | wl-copy`]);
+ if (root.cliphistBinary.includes("cliphist")) // Classic cliphist
+ Quickshell.execDetached(["bash", "-c", `printf '${StringUtils.shellSingleQuoteEscape(entry)}' | ${root.cliphistBinary} decode | wl-copy`]);
+ else { // Stash
+ const entryNumber = entry.split("\t")[0];
+ Quickshell.execDetached(["bash", "-c", `${root.cliphistBinary} decode ${entryNumber} | wl-copy`]);
+ }
+ }
+
+ function paste(entry) {
+ if (root.cliphistBinary.includes("cliphist")) // Classic cliphist
+ Quickshell.execDetached(["bash", "-c", `printf '${StringUtils.shellSingleQuoteEscape(entry)}' | ${root.cliphistBinary} decode | wl-copy && wl-paste`]);
+ else { // Stash
+ const entryNumber = entry.split("\t")[0];
+ Quickshell.execDetached(["bash", "-c", `${root.cliphistBinary} decode ${entryNumber} | wl-copy; ${root.pressPasteCommand}`]);
+ }
+ }
+
+ function superpaste(count, isImage = false) {
+ // Find entries
+ const targetEntries = entries.filter(entry => {
+ if (!isImage) return true;
+ return entryIsImage(entry);
+ }).slice(0, count)
+ const pasteCommands = [...targetEntries].reverse().map(entry => `printf '${StringUtils.shellSingleQuoteEscape(entry)}' | ${root.cliphistBinary} decode | wl-copy && sleep ${root.pasteDelay} && ${root.pressPasteCommand}`)
+ // Act
+ Quickshell.execDetached(["bash", "-c", pasteCommands.join(` && sleep ${root.pasteDelay} && `)]);
}
Process {
id: deleteProc
property string entry: ""
- command: ["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(deleteProc.entry)}' | cliphist delete`]
+ command: ["bash", "-c", `echo '${StringUtils.shellSingleQuoteEscape(deleteProc.entry)}' | ${root.cliphistBinary} delete`]
function deleteEntry(entry) {
deleteProc.entry = entry;
deleteProc.running = true;
@@ -81,8 +114,8 @@ Singleton {
Process {
id: readProc
property list buffer: []
-
- command: ["cliphist", "list"]
+
+ command: [root.cliphistBinary, "list"]
stdout: SplitParser {
onRead: (line) => {