Keep queued typing selections when reopening the menu
This commit is contained in:
1 parent
fbc6daea8b
commit
99f32458d6
5 files changed
+26
-7
No files matched your search
+12
-2
@@ -3,7 +3,7 @@
|
|||||||
# omarchy:summary=Pick one or multiple options from a menu
|
# omarchy:summary=Pick one or multiple options from a menu
|
||||||
# omarchy:group=menu
|
# omarchy:group=menu
|
||||||
# omarchy:name=select
|
# omarchy:name=select
|
||||||
# omarchy:args=prompt [option...] [-- --multiple --selected <value> --on-change <command-json> --width <pixels> --maxheight <pixels>]
|
# omarchy:args=prompt [option...] [-- --multiple --selected <value> --on-change <command-json> --change-key <key> --width <pixels> --maxheight <pixels>]
|
||||||
# omarchy:examples=omarchy menu select Format jpg png|omarchy-menu-select Resolution 4k 1080p 720p -- --width 400
|
# omarchy:examples=omarchy menu select Format jpg png|omarchy-menu-select Resolution 4k 1080p 720p -- --width 400
|
||||||
|
|
||||||
# An option may lead with an icon, as "<glyph><TAB><label>", and may trail a
|
# An option may lead with an icon, as "<glyph><TAB><label>", and may trail a
|
||||||
@@ -33,6 +33,7 @@ menu_width=""
|
|||||||
menu_maxheight=""
|
menu_maxheight=""
|
||||||
multiple=0
|
multiple=0
|
||||||
on_change="[]"
|
on_change="[]"
|
||||||
|
change_key=""
|
||||||
selected=()
|
selected=()
|
||||||
|
|
||||||
while (( $# > 0 )); do
|
while (( $# > 0 )); do
|
||||||
@@ -48,6 +49,14 @@ while (( $# > 0 )); do
|
|||||||
fi
|
fi
|
||||||
on_change="$1"
|
on_change="$1"
|
||||||
;;
|
;;
|
||||||
|
--change-key)
|
||||||
|
shift
|
||||||
|
if (( $# == 0 )); then
|
||||||
|
echo "omarchy-menu-select: --change-key requires a value" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
change_key="$1"
|
||||||
|
;;
|
||||||
--multiple)
|
--multiple)
|
||||||
multiple=1
|
multiple=1
|
||||||
;;
|
;;
|
||||||
@@ -110,13 +119,14 @@ payload=$(perl -MEncode=decode -MJSON::PP=encode_json,decode_json -e '
|
|||||||
multiple => $ARGV[6] ? JSON::PP::true : JSON::PP::false,
|
multiple => $ARGV[6] ? JSON::PP::true : JSON::PP::false,
|
||||||
selected => decode_json($ARGV[7]),
|
selected => decode_json($ARGV[7]),
|
||||||
onChange => decode_json($ARGV[8]),
|
onChange => decode_json($ARGV[8]),
|
||||||
|
changeKey => $ARGV[9],
|
||||||
selectionFile => decode("UTF-8", $ARGV[2]),
|
selectionFile => decode("UTF-8", $ARGV[2]),
|
||||||
doneFile => decode("UTF-8", $ARGV[3])
|
doneFile => decode("UTF-8", $ARGV[3])
|
||||||
};
|
};
|
||||||
$payload->{width} = int($ARGV[4]) if length($ARGV[4] // "");
|
$payload->{width} = int($ARGV[4]) if length($ARGV[4] // "");
|
||||||
$payload->{maxHeight} = int($ARGV[5]) if length($ARGV[5] // "");
|
$payload->{maxHeight} = int($ARGV[5]) if length($ARGV[5] // "");
|
||||||
print encode_json($payload)
|
print encode_json($payload)
|
||||||
' "$prompt" "$options_json" "$selection_file" "$done_file" "$menu_width" "$menu_maxheight" "$multiple" "$selected_json" "$on_change")
|
' "$prompt" "$options_json" "$selection_file" "$done_file" "$menu_width" "$menu_maxheight" "$multiple" "$selected_json" "$on_change" "$change_key")
|
||||||
|
|
||||||
omarchy-shell shell summon omarchy.menu "$payload" >/dev/null || exit 2
|
omarchy-shell shell summon omarchy.menu "$payload" >/dev/null || exit 2
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ def choose(title, catalog, selected, kind, overrides=None):
|
|||||||
rows = picker_rows(catalog, selected)
|
rows = picker_rows(catalog, selected)
|
||||||
args = ["omarchy-menu-select", title] + list(rows.values())
|
args = ["omarchy-menu-select", title] + list(rows.values())
|
||||||
on_change = ["python", str(setup.ROOT / "default/input-methods/typing.py"), "apply", kind, json.dumps({"catalog": catalog, "overrides": overrides or {}})]
|
on_change = ["python", str(setup.ROOT / "default/input-methods/typing.py"), "apply", kind, json.dumps({"catalog": catalog, "overrides": overrides or {}})]
|
||||||
args += ["--", "--multiple", "--width", "620", "--maxheight", "650", "--on-change", json.dumps(on_change)]
|
args += ["--", "--multiple", "--width", "620", "--maxheight", "650", "--on-change", json.dumps(on_change), "--change-key", "typing:" + kind]
|
||||||
for key in selected:
|
for key in selected:
|
||||||
args += ["--selected", rows[key][1:]]
|
args += ["--selected", rows[key][1:]]
|
||||||
result = subprocess.run(args, text=True, capture_output=True)
|
result = subprocess.run(args, text=True, capture_output=True)
|
||||||
|
|||||||
@@ -170,3 +170,5 @@ how the pickers behind menu actions (`omarchy-menu-plugin`,
|
|||||||
Pass `-- --multiple` to `omarchy-menu-select` for a multi-select request. Repeat `--selected <value>` to preselect returned values (labels plus any subtext, without icons). Clicking or pressing Enter toggles an option without closing the menu; Apply returns a JSON array in option order, including `[]` when all choices are deselected. Cancellation still exits 1. Selections survive filtering.
|
Pass `-- --multiple` to `omarchy-menu-select` for a multi-select request. Repeat `--selected <value>` to preselect returned values (labels plus any subtext, without icons). Clicking or pressing Enter toggles an option without closing the menu; Apply returns a JSON array in option order, including `[]` when all choices are deselected. Cancellation still exits 1. Selections survive filtering.
|
||||||
|
|
||||||
With `--on-change <JSON command array>`, each toggle runs that command with the proposed selection JSON appended as its final argument, and no Apply row is shown. The checkbox changes only after the command succeeds; a failed command retains the previous selection. Changes persist when the menu closes. The typing selectors use this mode.
|
With `--on-change <JSON command array>`, each toggle runs that command with the proposed selection JSON appended as its final argument, and no Apply row is shown. The checkbox changes only after the command succeeds; a failed command retains the previous selection. Changes persist when the menu closes. The typing selectors use this mode.
|
||||||
|
|
||||||
|
For immediate multi-select requests, `--change-key <key>` identifies the setting being changed across picker openings. The menu keeps queued selections for that key when reopened, so a new toggle cannot discard a change still being saved. Without a key, the command array identifies the setting.
|
||||||
@@ -59,6 +59,7 @@ Item {
|
|||||||
property var dmenuOptions: []
|
property var dmenuOptions: []
|
||||||
property bool dmenuMultiple: false
|
property bool dmenuMultiple: false
|
||||||
property var dmenuSelected: []
|
property var dmenuSelected: []
|
||||||
|
property string dmenuChangeKey: ""
|
||||||
property var dmenuOnChange: []
|
property var dmenuOnChange: []
|
||||||
property string selectionFile: ""
|
property string selectionFile: ""
|
||||||
property string doneFile: ""
|
property string doneFile: ""
|
||||||
@@ -908,7 +909,10 @@ Item {
|
|||||||
dmenuMultiple = mode === "select" && payload.multiple === true
|
dmenuMultiple = mode === "select" && payload.multiple === true
|
||||||
dmenuOnChange = dmenuMultiple && Array.isArray(payload.onChange)
|
dmenuOnChange = dmenuMultiple && Array.isArray(payload.onChange)
|
||||||
&& payload.onChange.every(function(arg) { return typeof arg === "string" }) ? payload.onChange : []
|
&& payload.onChange.every(function(arg) { return typeof arg === "string" }) ? payload.onChange : []
|
||||||
|
dmenuChangeKey = String(payload.changeKey || JSON.stringify(dmenuOnChange))
|
||||||
dmenuSelected = MenuModel.dmenuSelections(dmenuOptions, Array.isArray(payload.selected) ? payload.selected : [], dmenuOnChange.length > 0)
|
dmenuSelected = MenuModel.dmenuSelections(dmenuOptions, Array.isArray(payload.selected) ? payload.selected : [], dmenuOnChange.length > 0)
|
||||||
|
if (dmenuOnChange.length > 0)
|
||||||
|
dmenuSelected = MenuModel.dmenuSelections(dmenuOptions, selectionProc.requestedSelection(), true)
|
||||||
selectionFile = String(payload.selectionFile || "")
|
selectionFile = String(payload.selectionFile || "")
|
||||||
doneFile = String(payload.doneFile || "")
|
doneFile = String(payload.doneFile || "")
|
||||||
requestActive = !!doneFile
|
requestActive = !!doneFile
|
||||||
@@ -988,22 +992,23 @@ Item {
|
|||||||
Process {
|
Process {
|
||||||
id: selectionProc
|
id: selectionProc
|
||||||
property int serial: 0
|
property int serial: 0
|
||||||
|
property string changeKey: ""
|
||||||
property var selected: []
|
property var selected: []
|
||||||
property var queue: []
|
property var queue: []
|
||||||
property string collected: ""
|
property string collected: ""
|
||||||
|
|
||||||
function requestedSelection() {
|
function requestedSelection() {
|
||||||
for (var i = queue.length - 1; i >= 0; i--) {
|
for (var i = queue.length - 1; i >= 0; i--) {
|
||||||
if (queue[i].serial === root.requestSerial) return queue[i].selected
|
if (queue[i].key === root.dmenuChangeKey) return queue[i].selected
|
||||||
}
|
}
|
||||||
if (running && serial === root.requestSerial) return selected
|
if (running && changeKey === root.dmenuChangeKey) return selected
|
||||||
return root.dmenuSelected
|
return root.dmenuSelected
|
||||||
}
|
}
|
||||||
|
|
||||||
function enqueue(values) {
|
function enqueue(values) {
|
||||||
var selected = MenuModel.dmenuSelections(root.dmenuOptions, values, true)
|
var selected = MenuModel.dmenuSelections(root.dmenuOptions, values, true)
|
||||||
queue = queue.concat([{
|
queue = queue.concat([{
|
||||||
serial: root.requestSerial, selected: selected,
|
serial: root.requestSerial, key: root.dmenuChangeKey, selected: selected,
|
||||||
command: root.dmenuOnChange.concat([JSON.stringify(selected)])
|
command: root.dmenuOnChange.concat([JSON.stringify(selected)])
|
||||||
}])
|
}])
|
||||||
if (!running) startNext()
|
if (!running) startNext()
|
||||||
@@ -1014,6 +1019,7 @@ Item {
|
|||||||
var change = queue[0]
|
var change = queue[0]
|
||||||
queue = queue.slice(1)
|
queue = queue.slice(1)
|
||||||
serial = change.serial
|
serial = change.serial
|
||||||
|
changeKey = change.key
|
||||||
selected = change.selected
|
selected = change.selected
|
||||||
collected = ""
|
collected = ""
|
||||||
command = change.command
|
command = change.command
|
||||||
@@ -1025,7 +1031,7 @@ Item {
|
|||||||
onStreamFinished: selectionProc.collected = text
|
onStreamFinished: selectionProc.collected = text
|
||||||
}
|
}
|
||||||
onExited: function(exitCode) {
|
onExited: function(exitCode) {
|
||||||
if (serial === root.requestSerial && root.dmenuActive) {
|
if (changeKey === root.dmenuChangeKey && root.dmenuActive && root.dmenuOnChange.length > 0) {
|
||||||
if (exitCode === 0) {
|
if (exitCode === 0) {
|
||||||
var applied = selected
|
var applied = selected
|
||||||
if (collected.trim()) {
|
if (collected.trim()) {
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ class TypingSetupTest(unittest.TestCase):
|
|||||||
args = process.call_args.args[0]
|
args = process.call_args.args[0]
|
||||||
self.assertEqual(args[2], "\tKorean")
|
self.assertEqual(args[2], "\tKorean")
|
||||||
self.assertIn("--multiple", args)
|
self.assertIn("--multiple", args)
|
||||||
|
self.assertEqual(args[args.index("--change-key") + 1], "typing:input")
|
||||||
self.assertEqual(args[-2:], ["--selected", "Korean"])
|
self.assertEqual(args[-2:], ["--selected", "Korean"])
|
||||||
|
|
||||||
def test_apply_rejects_unknown_values(self):
|
def test_apply_rejects_unknown_values(self):
|
||||||
|
|||||||
Reference in new issue
Block a user