aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/assistant/Assistant.qml
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-16 16:20:01 +0200
committerDanilo M. <danix@danix.xyz>2026-10-16 16:20:01 +0200
commit12d6830424d24f5a2ed8056b53a12cc4b978ece2 (patch)
treea52a30ab446acd718aa67e1c8dc2887a472954cb /desktop/assistant/Assistant.qml
parentf6ceae477979b32869c0c17e2b1fc05477d6eb81 (diff)
downloadquickshell-12d6830424d24f5a2ed8056b53a12cc4b978ece2.tar.gz
quickshell-12d6830424d24f5a2ed8056b53a12cc4b978ece2.zip
feat(assistant): tell a nameless file's kind from its content
A script with no suffix staged as 'other' and was refused. A staged file the name says nothing about is now handed to file(1) once, and its mime type gives the kind, so a shell script is code and gets Explain and Review. The daemon makes its own call on the content. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop/assistant/Assistant.qml')
-rw-r--r--desktop/assistant/Assistant.qml32
1 files changed, 31 insertions, 1 deletions
diff --git a/desktop/assistant/Assistant.qml b/desktop/assistant/Assistant.qml
index 977b4dd..0139ef9 100644
--- a/desktop/assistant/Assistant.qml
+++ b/desktop/assistant/Assistant.qml
@@ -105,10 +105,40 @@ Scope {
root.staged = files;
root.historyOpen = root.pickerOpen = false;
root.open = true;
+ root.refine();
}
function stage(path) {
- if (!root.staged.some(f => f.path === path)) root.staged = root.staged.concat([Files.file(path)]);
+ if (root.staged.some(f => f.path === path)) return;
+ root.staged = root.staged.concat([Files.file(path)]);
+ root.refine();
+ }
+
+ // A file whose name says nothing (a script with no suffix) is "other"
+ // until file(1) has read it. One run for all of them; the daemon makes
+ // its own call on the content when the question is sent.
+ function refine() {
+ const unknown = root.staged.filter(f => f.kind === "other").map(f => f.path);
+ if (!unknown.length) return;
+ sniff.paths = unknown;
+ sniff.running = false; // a running Process ignores running = true
+ sniff.running = true;
+ }
+
+ Process {
+ id: sniff
+ property var paths: []
+ command: ["file", "-b", "--mime-type", "--"].concat(paths)
+ stdout: StdioCollector {
+ onStreamFinished: {
+ const mimes = text.trim().split("\n");
+ root.staged = root.staged.map(f => {
+ const i = sniff.paths.indexOf(f.path);
+ return i < 0 || f.kind !== "other" ? f
+ : Object.assign({}, f, { kind: Files.fromMime(mimes[i] ?? "") });
+ });
+ }
+ }
}
function unstage(i) {
const s = root.staged.slice();