From 9c6bbac7ef09213dd0e6523f30eb328716015d14 Mon Sep 17 00:00:00 2001 From: Tin Lai Date: Sun, 21 Jul 2024 19:14:05 +1000 Subject: [PATCH 01/10] implements if conditions for pane and window Signed-off-by: Tin Lai --- src/tmuxp/workspace/loader.py | 60 +++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/src/tmuxp/workspace/loader.py b/src/tmuxp/workspace/loader.py index 58da0ee91a..2e616e8670 100644 --- a/src/tmuxp/workspace/loader.py +++ b/src/tmuxp/workspace/loader.py @@ -8,6 +8,49 @@ logger = logging.getLogger(__name__) +def optional_windows_and_pane( + workspace_dict: t.Dict[str, t.Any], +) -> bool: + """Determine if a window or pane should be included based on `if` conditions. + + The function evaluates the 'if' condition specified in `workspace_dict` to determine inclusion: + - If 'if' key is not present, it defaults to True. + - If 'if' is a string or boolean, it's treated as a shell variable. + - 'if' can be a dictionary containing 'shell' or 'python' keys with valid expressions. + - 'shell' expressions are expanded and checked against true values ('y', 'yes', '1', 'on', 'true', 't'). + - 'python' expressions are evaluated using `eval()` + + Parameters + ---------- + workspace_dict : Dict + A dictionary containing pane/window configuration data. + + Returns + ------- + bool + True if the window or pane should be included, False otherwise. + """ + if "if" not in workspace_dict: + return True + if_cond = workspace_dict["if"] + if isinstance(if_cond, (str, bool)): + # treat this as shell variable + if_cond = {"shell": if_cond} + if not isinstance(if_cond, dict) or not ("shell" in if_cond or "python" in if_cond): + raise ValueError(f"if conditions does not contains valid expression: {if_cond}") + if "shell" in if_cond: + if isinstance(if_cond["shell"], str): + if expandshell(if_cond["shell"]).lower() not in ("y", "yes", "1", "on", "true", "t"): + return False + elif isinstance(if_cond["shell"], bool): + if not if_cond["shell"]: + return False + if "python" in if_cond: + if if_cond["python"] and not eval(if_cond["python"]): # dangerous + return False + return True + + def expandshell(value: str) -> str: """Resolve shell variables based on user's ``$HOME`` and ``env``. @@ -170,18 +213,21 @@ def expand( # recurse into window and pane workspace items if "windows" in workspace_dict: - workspace_dict["windows"] = [ - expand(window, parent=workspace_dict) - for window in workspace_dict["windows"] - ] + window_dicts = workspace_dict["windows"] + window_dicts = filter(optional_windows_and_pane, window_dicts) + window_dicts = map(lambda x: expand(x, parent=workspace_dict), window_dicts) + # remove windows that has no panels (e.g. due to if conditions) + window_dicts = filter(lambda x: len(x["panes"]), window_dicts) + workspace_dict["windows"] = list(window_dicts) + elif "panes" in workspace_dict: pane_dicts = workspace_dict["panes"] for pane_idx, pane_dict in enumerate(pane_dicts): pane_dicts[pane_idx] = {} pane_dicts[pane_idx].update(expand_cmd(pane_dict)) - workspace_dict["panes"] = [ - expand(pane, parent=workspace_dict) for pane in pane_dicts - ] + pane_dicts = filter(optional_windows_and_pane, pane_dicts) + pane_dicts = map(lambda x: expand(x, parent=workspace_dict), pane_dicts) + workspace_dict["panes"] = list(pane_dicts) return workspace_dict From f9d1f4d6ec70658c997330ef5bb8f20b172eb0f5 Mon Sep 17 00:00:00 2001 From: Tin Lai Date: Sun, 21 Jul 2024 19:46:08 +1000 Subject: [PATCH 02/10] add workspace provided envars when not presents in current environ Signed-off-by: Tin Lai --- src/tmuxp/workspace/loader.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tmuxp/workspace/loader.py b/src/tmuxp/workspace/loader.py index 2e616e8670..dfd5496625 100644 --- a/src/tmuxp/workspace/loader.py +++ b/src/tmuxp/workspace/loader.py @@ -157,6 +157,9 @@ def expand( if any(val.startswith(a) for a in [".", "./"]): val = str(cwd / val) workspace_dict["environment"][key] = val + if key not in os.environ: + # using user provided environment variable as default vars + os.environ[key] = val if "global_options" in workspace_dict: for key in workspace_dict["global_options"]: val = workspace_dict["global_options"][key] From a886b7f45ce047bdd6535133856080e7ac3014f2 Mon Sep 17 00:00:00 2001 From: Tin Lai Date: Sun, 21 Jul 2024 19:46:20 +1000 Subject: [PATCH 03/10] add docs Signed-off-by: Tin Lai --- docs/configuration/examples.md | 35 ++++++++++++++++++++++++ examples/if-conditions.json | 49 ++++++++++++++++++++++++++++++++++ examples/if-conditions.yaml | 29 ++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 examples/if-conditions.json create mode 100644 examples/if-conditions.yaml diff --git a/docs/configuration/examples.md b/docs/configuration/examples.md index 010b039c17..17ab54f56e 100644 --- a/docs/configuration/examples.md +++ b/docs/configuration/examples.md @@ -287,6 +287,41 @@ newer and tmux 3.0 or newer. ```` +## `if` conditions + +tmuxp enables one to optionally open windows / panes based on coditions. The `if` conditions can appears in the configuration for window or pane. + +````{tab} YAML + +```{literalinclude} ../../examples/if-conditions.yaml +:language: yaml + +``` +```` + +````{tab} JSON + +```{literalinclude} ../../examples/if-conditions.json +:language: json + +``` + +```` + +In the example, running the example + +```console +$ tmuxp load examples/if-conditions.yaml +``` + +should produce **only** a window with upper and lower split panes (others should have `if` conditions that evaluates to false). This example allows for on-demand pane showing, where + +```console +$ show_htop=false tmuxp load examples/if-conditions.yaml +``` + +will insteads suppress the `htop` command pane and resulting in a different behaviour. + ## Focusing tmuxp allows `focus: true` for assuring windows and panes are attached / diff --git a/examples/if-conditions.json b/examples/if-conditions.json new file mode 100644 index 0000000000..1765326243 --- /dev/null +++ b/examples/if-conditions.json @@ -0,0 +1,49 @@ +{ + "session_name": "if conditions test", + "environment": { + "Foo": "false", + "show_htop": "true" + }, + "windows": [ + { + "window_name": "window 1 ${ha} $Foo", + "if": { + "shell": "${Foo}" + }, + "panes": [ + { + "shell_command": [ + "echo \"this shouldn't shows up\"" + ] + }, + "echo neither should this $Foo" + ] + }, + { + "window_name": "window 2", + "panes": [ + { + "if": { + "python": "1+1==3" + }, + "shell_command": [ + "echo the above is a false statement" + ] + }, + { + "shell_command": [ + "echo no condition", + "python -m http.server" + ] + }, + { + "if": "${show_htop}", + "shell_command": [ + "echo the above is a true statement (by default), but can be disabled on-demand", + "htop" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/examples/if-conditions.yaml b/examples/if-conditions.yaml new file mode 100644 index 0000000000..425aec4325 --- /dev/null +++ b/examples/if-conditions.yaml @@ -0,0 +1,29 @@ +session_name: if conditions test +environment: + Foo: 'false' + show_htop: 'true' +windows: + # the following would not shows up as it evaluates to false + - window_name: window 1 ${ha} $Foo + if: + shell: ${Foo} + panes: + - shell_command: + - echo "this shouldn't shows up" + - echo neither should this $Foo + - window_name: window 2 + panes: + # should not shows up + - if: + python: 1+1==3 + shell_command: + - echo the above is a false statement + # no if conditions + - shell_command: + - echo no condition + - python -m http.server + # display by default, but can be disabled by running `show_htop=false tmuxp load .....` + - if: ${show_htop} + shell_command: + - echo the above is a true statement (by default), but can be disabled on-demand + - htop From e95fda969d2bcd4f5d789cb28e9aaf2c5315bdbc Mon Sep 17 00:00:00 2001 From: Tin Lai Date: Mon, 22 Jul 2024 21:23:01 +1000 Subject: [PATCH 04/10] support shell expression and python statements Signed-off-by: Tin Lai --- examples/if-conditions.yaml | 17 +++++++++-------- src/tmuxp/workspace/loader.py | 30 ++++++++++++++++++------------ 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/examples/if-conditions.yaml b/examples/if-conditions.yaml index 425aec4325..077f6ce385 100644 --- a/examples/if-conditions.yaml +++ b/examples/if-conditions.yaml @@ -5,25 +5,26 @@ environment: windows: # the following would not shows up as it evaluates to false - window_name: window 1 ${ha} $Foo - if: - shell: ${Foo} + if: ${Foo} panes: - shell_command: - echo "this shouldn't shows up" - echo neither should this $Foo - window_name: window 2 panes: - # should not shows up + # should not shows up; using shell expression - if: - python: 1+1==3 + shell: '[ 5 -lt 4 ]' shell_command: - echo the above is a false statement - # no if conditions - - shell_command: - - echo no condition + # python conditions + - if: + python: import os; os.path.isdir('${PWD}') + shell_command: + - echo "checking for PWD (${PWD}) is a directory in python" - python -m http.server # display by default, but can be disabled by running `show_htop=false tmuxp load .....` - if: ${show_htop} shell_command: - - echo the above is a true statement (by default), but can be disabled on-demand + - echo "the above is a true statement (by default), but can be disabled on-demand" - htop diff --git a/src/tmuxp/workspace/loader.py b/src/tmuxp/workspace/loader.py index dfd5496625..67bd6060fa 100644 --- a/src/tmuxp/workspace/loader.py +++ b/src/tmuxp/workspace/loader.py @@ -3,6 +3,7 @@ import logging import os import pathlib +import subprocess import typing as t logger = logging.getLogger(__name__) @@ -16,9 +17,10 @@ def optional_windows_and_pane( The function evaluates the 'if' condition specified in `workspace_dict` to determine inclusion: - If 'if' key is not present, it defaults to True. - If 'if' is a string or boolean, it's treated as a shell variable. - - 'if' can be a dictionary containing 'shell' or 'python' keys with valid expressions. - - 'shell' expressions are expanded and checked against true values ('y', 'yes', '1', 'on', 'true', 't'). - - 'python' expressions are evaluated using `eval()` + - 'if' can be a dictionary containing 'shell', 'shell_var' or 'python' keys with valid expressions. + - 'shell_var' expressions are expanded and checked against true values ('y', 'yes', '1', 'on', 'true', 't'). + - 'shell' expressions are evaluated using subprocess + - 'python' expressions are evaluated using `exec()` Parameters ---------- @@ -35,18 +37,22 @@ def optional_windows_and_pane( if_cond = workspace_dict["if"] if isinstance(if_cond, (str, bool)): # treat this as shell variable - if_cond = {"shell": if_cond} - if not isinstance(if_cond, dict) or not ("shell" in if_cond or "python" in if_cond): + if_cond = {"shell_var": if_cond} + if not isinstance(if_cond, dict) or not any(predicate in if_cond for predicate in ("python", "shell", "shell_var")): raise ValueError(f"if conditions does not contains valid expression: {if_cond}") + if "shell_var" in if_cond: + if expandshell(str(if_cond["shell_var"])).lower() not in ("y", "yes", "1", "on", "true", "t"): + return False if "shell" in if_cond: - if isinstance(if_cond["shell"], str): - if expandshell(if_cond["shell"]).lower() not in ("y", "yes", "1", "on", "true", "t"): - return False - elif isinstance(if_cond["shell"], bool): - if not if_cond["shell"]: - return False + if subprocess.run(if_cond["shell"], shell=True).returncode != 0: + return False if "python" in if_cond: - if if_cond["python"] and not eval(if_cond["python"]): # dangerous + # assign the result of the last statement from the python snippet + py_statements = if_cond["python"].split(";") + py_statements[-1] = f"ret={py_statements[-1]}" + locals = {} + exec(";".join(py_statements), {}, locals) + if not locals['ret']: return False return True From 5c3807923da3f4045cf55556a6e43357176d5054 Mon Sep 17 00:00:00 2001 From: Tin Lai Date: Mon, 22 Jul 2024 22:01:40 +1000 Subject: [PATCH 05/10] fix grammars --- docs/configuration/examples.md | 4 ++-- examples/if-conditions.json | 13 +++++++------ examples/if-conditions.yaml | 4 ++-- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/configuration/examples.md b/docs/configuration/examples.md index 17ab54f56e..8fd8091a87 100644 --- a/docs/configuration/examples.md +++ b/docs/configuration/examples.md @@ -289,7 +289,7 @@ newer and tmux 3.0 or newer. ## `if` conditions -tmuxp enables one to optionally open windows / panes based on coditions. The `if` conditions can appears in the configuration for window or pane. +tmuxp enables one to optionally open windows / panes based on conditions. The `if` conditions can appears in the configuration for window or pane. ````{tab} YAML @@ -320,7 +320,7 @@ should produce **only** a window with upper and lower split panes (others should $ show_htop=false tmuxp load examples/if-conditions.yaml ``` -will insteads suppress the `htop` command pane and resulting in a different behaviour. +will instead suppress the `htop` command pane and resulting in a different behaviour. ## Focusing diff --git a/examples/if-conditions.json b/examples/if-conditions.json index 1765326243..4c34e8eae5 100644 --- a/examples/if-conditions.json +++ b/examples/if-conditions.json @@ -7,9 +7,7 @@ "windows": [ { "window_name": "window 1 ${ha} $Foo", - "if": { - "shell": "${Foo}" - }, + "if": "${Foo}", "panes": [ { "shell_command": [ @@ -24,22 +22,25 @@ "panes": [ { "if": { - "python": "1+1==3" + "shell": "[ 5 -lt 4 ]" }, "shell_command": [ "echo the above is a false statement" ] }, { + "if": { + "python": "import os; os.path.isdir('${PWD}')" + }, "shell_command": [ - "echo no condition", + "echo \"checking for PWD (${PWD}) is a directory in python\"", "python -m http.server" ] }, { "if": "${show_htop}", "shell_command": [ - "echo the above is a true statement (by default), but can be disabled on-demand", + "echo \"the above is a true statement (by default), but can be disabled on-demand\"", "htop" ] } diff --git a/examples/if-conditions.yaml b/examples/if-conditions.yaml index 077f6ce385..6d07b87441 100644 --- a/examples/if-conditions.yaml +++ b/examples/if-conditions.yaml @@ -12,12 +12,12 @@ windows: - echo neither should this $Foo - window_name: window 2 panes: - # should not shows up; using shell expression + # shell expression condition; should not show up - if: shell: '[ 5 -lt 4 ]' shell_command: - echo the above is a false statement - # python conditions + # python condition - if: python: import os; os.path.isdir('${PWD}') shell_command: From abd97718bdeeff1107a7ac778ccb52aa3698c8bf Mon Sep 17 00:00:00 2001 From: Tin Lai Date: Mon, 22 Jul 2024 22:13:06 +1000 Subject: [PATCH 06/10] add tests for if conditions Signed-off-by: Tin Lai --- examples/if-conditions-test.yaml | 48 ++++++++++++++++++++++++++++++++ examples/if-conditions.yaml | 2 +- tests/workspace/test_builder.py | 28 +++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 examples/if-conditions-test.yaml diff --git a/examples/if-conditions-test.yaml b/examples/if-conditions-test.yaml new file mode 100644 index 0000000000..95b84ac8c6 --- /dev/null +++ b/examples/if-conditions-test.yaml @@ -0,0 +1,48 @@ +session_name: if conditions test conditions +environment: + foo: 'false' + bar: '1' + F: '0' +windows: + - window_name: window all false + panes: + - if: ${foo} + shell_command: + - echo pane 1 + - if: + shell: '[ 1 -gt 2 ]' + shell_command: + - echo pane 2 + - if: + shell_var: ${F} + - window_name: window 2 of 3 true + panes: + - if: + shell: '[ "foo" = "bar" ]' + shell_command: + - echo pane 3 + - if: + shell: '[ "hello" != "byte" ]' + shell_command: + - echo pane 4 + - if: + python: '2**4 == 16' + shell_command: + - echo pane 5 + - window_name: window 2 of 4 true + panes: + - if: + shell_var: 'FALSE' + shell_command: + - echo pane 6 + - if: + shell_var: ${bar} + shell_command: + - echo pane 7 + - if: + python: import os; not os.path.isdir('/a/very/random/path') + shell_command: + - echo pane 8 + - if: ${non_existing_var} + shell_command: + - echo pane 9 diff --git a/examples/if-conditions.yaml b/examples/if-conditions.yaml index 6d07b87441..b8871d93be 100644 --- a/examples/if-conditions.yaml +++ b/examples/if-conditions.yaml @@ -19,7 +19,7 @@ windows: - echo the above is a false statement # python condition - if: - python: import os; os.path.isdir('${PWD}') + python: import os; os.path.isdir(os.path.expandvars('${PWD}')) shell_command: - echo "checking for PWD (${PWD}) is a directory in python" - python -m http.server diff --git a/tests/workspace/test_builder.py b/tests/workspace/test_builder.py index 801b462d5a..692d01ed9d 100644 --- a/tests/workspace/test_builder.py +++ b/tests/workspace/test_builder.py @@ -563,6 +563,34 @@ def test_blank_pane_spawn( assert len(window4.panes) == 2 +def test_if_conditions( + session: Session, +) -> None: + """ + Test various ways of spawning panes with conditions from a tmuxp configuration. + """ + yaml_workspace_file = EXAMPLE_PATH / "if-conditions-test.yaml" + test_config = ConfigReader._from_file(yaml_workspace_file) + + test_config = loader.expand(test_config) + builder = WorkspaceBuilder(session_config=test_config, server=session.server) + builder.build(session=session) + + assert session == builder.session + + with pytest.raises(ObjectDoesNotExist): + window1 = session.windows.get(window_name="window all false") + assert window1 is None + + window2 = session.windows.get(window_name="window 2 of 3 true") + assert window2 is not None + assert len(window2.panes) == 2 + + window3 = session.windows.get(window_name="window 2 of 4 true") + assert window3 is not None + assert len(window3.panes) == 2 + + def test_start_directory(session: Session, tmp_path: pathlib.Path) -> None: """Test workspace builder setting start_directory relative to current directory.""" test_dir = tmp_path / "foo bar" From 5b2797417378439ff8467cd29943050ebaca41ee Mon Sep 17 00:00:00 2001 From: Tin Lai Date: Mon, 22 Jul 2024 22:18:16 +1000 Subject: [PATCH 07/10] linting Signed-off-by: Tin Lai --- src/tmuxp/workspace/loader.py | 24 +++++++++++++++++------- tests/workspace/test_builder.py | 4 +--- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/tmuxp/workspace/loader.py b/src/tmuxp/workspace/loader.py index 67bd6060fa..b4512bc173 100644 --- a/src/tmuxp/workspace/loader.py +++ b/src/tmuxp/workspace/loader.py @@ -38,13 +38,23 @@ def optional_windows_and_pane( if isinstance(if_cond, (str, bool)): # treat this as shell variable if_cond = {"shell_var": if_cond} - if not isinstance(if_cond, dict) or not any(predicate in if_cond for predicate in ("python", "shell", "shell_var")): - raise ValueError(f"if conditions does not contains valid expression: {if_cond}") + if not isinstance(if_cond, dict) or not any( + predicate in if_cond for predicate in ("python", "shell", "shell_var") + ): + msg = f"if conditions does not contains valid expression: {if_cond}" + raise ValueError(msg) if "shell_var" in if_cond: - if expandshell(str(if_cond["shell_var"])).lower() not in ("y", "yes", "1", "on", "true", "t"): + if expandshell(str(if_cond["shell_var"])).lower() not in { + "y", + "yes", + "1", + "on", + "true", + "t", + }: return False if "shell" in if_cond: - if subprocess.run(if_cond["shell"], shell=True).returncode != 0: + if subprocess.run(if_cond["shell"], shell=True, check=False).returncode != 0: return False if "python" in if_cond: # assign the result of the last statement from the python snippet @@ -52,7 +62,7 @@ def optional_windows_and_pane( py_statements[-1] = f"ret={py_statements[-1]}" locals = {} exec(";".join(py_statements), {}, locals) - if not locals['ret']: + if not locals["ret"]: return False return True @@ -224,7 +234,7 @@ def expand( if "windows" in workspace_dict: window_dicts = workspace_dict["windows"] window_dicts = filter(optional_windows_and_pane, window_dicts) - window_dicts = map(lambda x: expand(x, parent=workspace_dict), window_dicts) + window_dicts = (expand(x, parent=workspace_dict) for x in window_dicts) # remove windows that has no panels (e.g. due to if conditions) window_dicts = filter(lambda x: len(x["panes"]), window_dicts) workspace_dict["windows"] = list(window_dicts) @@ -235,7 +245,7 @@ def expand( pane_dicts[pane_idx] = {} pane_dicts[pane_idx].update(expand_cmd(pane_dict)) pane_dicts = filter(optional_windows_and_pane, pane_dicts) - pane_dicts = map(lambda x: expand(x, parent=workspace_dict), pane_dicts) + pane_dicts = (expand(x, parent=workspace_dict) for x in pane_dicts) workspace_dict["panes"] = list(pane_dicts) return workspace_dict diff --git a/tests/workspace/test_builder.py b/tests/workspace/test_builder.py index 692d01ed9d..a36f7e7836 100644 --- a/tests/workspace/test_builder.py +++ b/tests/workspace/test_builder.py @@ -566,9 +566,7 @@ def test_blank_pane_spawn( def test_if_conditions( session: Session, ) -> None: - """ - Test various ways of spawning panes with conditions from a tmuxp configuration. - """ + """Test various ways of spawning panes with conditions from a tmuxp configuration.""" yaml_workspace_file = EXAMPLE_PATH / "if-conditions-test.yaml" test_config = ConfigReader._from_file(yaml_workspace_file) From 1ac1d8ec23bdeb0b665a502989c6f376ebdf34e4 Mon Sep 17 00:00:00 2001 From: Tin Lai Date: Mon, 22 Jul 2024 22:21:31 +1000 Subject: [PATCH 08/10] fix grammar Signed-off-by: Tin Lai --- examples/if-conditions.json | 2 +- examples/if-conditions.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/if-conditions.json b/examples/if-conditions.json index 4c34e8eae5..815bd192c3 100644 --- a/examples/if-conditions.json +++ b/examples/if-conditions.json @@ -11,7 +11,7 @@ "panes": [ { "shell_command": [ - "echo \"this shouldn't shows up\"" + "echo \"this shouldn't show up\"" ] }, "echo neither should this $Foo" diff --git a/examples/if-conditions.yaml b/examples/if-conditions.yaml index b8871d93be..b11e884d69 100644 --- a/examples/if-conditions.yaml +++ b/examples/if-conditions.yaml @@ -3,12 +3,12 @@ environment: Foo: 'false' show_htop: 'true' windows: - # the following would not shows up as it evaluates to false + # the following would not show up as it evaluates to false - window_name: window 1 ${ha} $Foo if: ${Foo} panes: - shell_command: - - echo "this shouldn't shows up" + - echo "this shouldn't show up" - echo neither should this $Foo - window_name: window 2 panes: From 5b1e30d0aaea8f8c74274b341008e829700ba69f Mon Sep 17 00:00:00 2001 From: Tin Lai Date: Mon, 22 Jul 2024 22:30:12 +1000 Subject: [PATCH 09/10] more comprehensive example that uses pipe and grep Signed-off-by: Tin Lai --- examples/if-conditions-test.yaml | 5 +++++ src/tmuxp/workspace/loader.py | 7 ++++++- tests/workspace/test_builder.py | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/if-conditions-test.yaml b/examples/if-conditions-test.yaml index 95b84ac8c6..345f95a74a 100644 --- a/examples/if-conditions-test.yaml +++ b/examples/if-conditions-test.yaml @@ -3,6 +3,7 @@ environment: foo: 'false' bar: '1' F: '0' + MY_VAR: myfoobar windows: - window_name: window all false panes: @@ -46,3 +47,7 @@ windows: - if: ${non_existing_var} shell_command: - echo pane 9 + - if: + shell: echo ${MY_VAR} | grep -q foo + shell_command: + - echo pane 10 diff --git a/src/tmuxp/workspace/loader.py b/src/tmuxp/workspace/loader.py index b4512bc173..02091a9367 100644 --- a/src/tmuxp/workspace/loader.py +++ b/src/tmuxp/workspace/loader.py @@ -54,7 +54,12 @@ def optional_windows_and_pane( }: return False if "shell" in if_cond: - if subprocess.run(if_cond["shell"], shell=True, check=False).returncode != 0: + if ( + subprocess.run( + expandshell(if_cond["shell"]), shell=True, check=False + ).returncode + != 0 + ): return False if "python" in if_cond: # assign the result of the last statement from the python snippet diff --git a/tests/workspace/test_builder.py b/tests/workspace/test_builder.py index a36f7e7836..cf5d6d05e2 100644 --- a/tests/workspace/test_builder.py +++ b/tests/workspace/test_builder.py @@ -586,7 +586,7 @@ def test_if_conditions( window3 = session.windows.get(window_name="window 2 of 4 true") assert window3 is not None - assert len(window3.panes) == 2 + assert len(window3.panes) == 3 def test_start_directory(session: Session, tmp_path: pathlib.Path) -> None: From 3cfc5df3edb4a4cb767d1c122f01ccf3a35d568d Mon Sep 17 00:00:00 2001 From: Tin Lai Date: Mon, 22 Jul 2024 22:36:12 +1000 Subject: [PATCH 10/10] ruff Signed-off-by: Tin Lai --- src/tmuxp/workspace/loader.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/tmuxp/workspace/loader.py b/src/tmuxp/workspace/loader.py index 02091a9367..b8d35b8b31 100644 --- a/src/tmuxp/workspace/loader.py +++ b/src/tmuxp/workspace/loader.py @@ -53,14 +53,15 @@ def optional_windows_and_pane( "t", }: return False - if "shell" in if_cond: - if ( - subprocess.run( - expandshell(if_cond["shell"]), shell=True, check=False - ).returncode - != 0 - ): - return False + if "shell" in if_cond and ( + subprocess.run( + expandshell(if_cond["shell"]), + shell=True, + check=False, + ).returncode + != 0 + ): + return False if "python" in if_cond: # assign the result of the last statement from the python snippet py_statements = if_cond["python"].split(";")