Skip to content

Commit 4ad9d10

Browse files
authored
feat(freeze): Allow running command without needing input (#701)
This will let args be passed to tmuxp freeze without needed additional cli input. This way it can be ran in a single command without interruption, e.g. able to bind to a keyboard shortcut or script, or headless task. Credit @davidatbu
2 parents d2c1b56 + 0322895 commit 4ad9d10

File tree

3 files changed

+98
-50
lines changed

3 files changed

+98
-50
lines changed

CHANGES

+10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@
66

77
#### What's new
88

9+
- #701: `tmuxp freeze` now accepts `--quiet` and `--yes` along with the
10+
`--config-format` and filename (`--save-to`). This means you can do it all in
11+
one command:
12+
13+
`tmuxp freeze -yqo .tmuxp.yaml`
14+
15+
Or bind it to `.tmux.conf` itself: `bind -T root C-s run-shell "tmuxp freeze -yqo .tmuxp.yaml"`
16+
17+
Credit: [@davidatbu](https://github.com/davidatbu)
18+
919
- #672: Panes now accept `shell` for their initial command.
1020

1121
Equivalent to `tmux split-windows`'s `[shell-command]`

tests/test_cli.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -868,16 +868,16 @@ def test_import_tmuxinator(cli_args, inputs, tmpdir, monkeypatch):
868868
@pytest.mark.parametrize(
869869
"cli_args,inputs",
870870
[
871-
(['freeze', 'myfrozensession'], ['\n', 'y\n', './la.yaml\n', 'y\n']),
871+
(['freeze', 'myfrozensession'], ['y\n', './la.yaml\n', 'y\n']),
872872
( # Exists
873873
['freeze', 'myfrozensession'],
874-
['\n', 'y\n', './exists.yaml\n', './la.yaml\n', 'y\n'],
874+
['y\n', './exists.yaml\n', './la.yaml\n', 'y\n'],
875875
),
876876
( # Imply current session if not entered
877877
['freeze'],
878-
['\n', 'y\n', './la.yaml\n', 'y\n'],
878+
['y\n', './la.yaml\n', 'y\n'],
879879
),
880-
(['freeze'], ['\n', 'y\n', './exists.yaml\n', './la.yaml\n', 'y\n']), # Exists
880+
(['freeze'], ['y\n', './exists.yaml\n', './la.yaml\n', 'y\n']), # Exists
881881
],
882882
)
883883
def test_freeze(server, cli_args, inputs, tmpdir, monkeypatch):

tmuxp/cli.py

+84-46
Original file line numberDiff line numberDiff line change
@@ -911,8 +911,33 @@ def command_shell(
911911
@click.argument('session_name', nargs=1, required=False)
912912
@click.option('-S', 'socket_path', help='pass-through for tmux -S')
913913
@click.option('-L', 'socket_name', help='pass-through for tmux -L')
914+
@click.option(
915+
'-f',
916+
'--config-format',
917+
type=click.Choice(['yaml', 'json']),
918+
help='format to save in',
919+
)
920+
@click.option('-o', '--save-to', type=click.Path(exists=False), help='file to save to')
921+
@click.option(
922+
'-y',
923+
'--yes',
924+
type=bool,
925+
is_flag=True,
926+
default=False,
927+
help="Don't prompt for confirmation",
928+
)
929+
@click.option(
930+
'-q',
931+
'--quiet',
932+
type=bool,
933+
is_flag=True,
934+
default=False,
935+
help="Don't prompt for confirmation",
936+
)
914937
@click.option('--force', 'force', help='overwrite the config file', is_flag=True)
915-
def command_freeze(session_name, socket_name, socket_path, force):
938+
def command_freeze(
939+
session_name, socket_name, config_format, save_to, socket_path, yes, quiet, force
940+
):
916941
"""Snapshot a session into a config.
917942
918943
If SESSION_NAME is provided, snapshot that session. Otherwise, use the
@@ -936,61 +961,74 @@ def command_freeze(session_name, socket_name, socket_path, force):
936961
configparser = kaptan.Kaptan()
937962
newconfig = config.inline(sconf)
938963
configparser.import_config(newconfig)
939-
config_format = click.prompt(
940-
'Convert to', value_proc=_validate_choices(['yaml', 'json']), default='yaml'
941-
)
964+
965+
if not quiet:
966+
print(
967+
'---------------------------------------------------------------'
968+
'\n'
969+
'Freeze does its best to snapshot live tmux sessions.\n'
970+
)
971+
if not (
972+
yes
973+
or click.confirm(
974+
'The new config *WILL* require adjusting afterwards. Save config?'
975+
)
976+
):
977+
if not quiet:
978+
print(
979+
'tmuxp has examples in JSON and YAML format at '
980+
'<http://tmuxp.git-pull.com/examples.html>\n'
981+
'View tmuxp docs at <http://tmuxp.git-pull.com/>.'
982+
)
983+
sys.exit()
984+
985+
dest = save_to
986+
while not dest:
987+
save_to = os.path.abspath(
988+
os.path.join(
989+
get_config_dir(),
990+
'%s.%s' % (sconf.get('session_name'), config_format or 'yaml'),
991+
)
992+
)
993+
dest_prompt = click.prompt(
994+
'Save to: %s' % save_to, value_proc=get_abs_path, default=save_to
995+
)
996+
if not force and os.path.exists(dest_prompt):
997+
print('%s exists. Pick a new filename.' % dest_prompt)
998+
continue
999+
1000+
dest = dest_prompt
1001+
dest = os.path.abspath(os.path.relpath(os.path.expanduser(dest)))
1002+
1003+
if config_format is None:
1004+
valid_config_formats = ['json', 'yaml']
1005+
_, config_format = os.path.splitext(dest)
1006+
config_format = config_format[1:].lower()
1007+
if config_format not in valid_config_formats:
1008+
config_format = click.prompt(
1009+
"Couldn't ascertain one of [%s] from file name. Convert to"
1010+
% ", ".join(valid_config_formats),
1011+
value_proc=_validate_choices(['yaml', 'json']),
1012+
default='yaml',
1013+
)
9421014

9431015
if config_format == 'yaml':
9441016
newconfig = configparser.export(
9451017
'yaml', indent=2, default_flow_style=False, safe=True
9461018
)
9471019
elif config_format == 'json':
9481020
newconfig = configparser.export('json', indent=2)
949-
else:
950-
sys.exit('Unknown config format.')
9511021

952-
print(
953-
'---------------------------------------------------------------'
954-
'\n'
955-
'Freeze does its best to snapshot live tmux sessions.\n'
956-
)
957-
if click.confirm(
958-
'The new config *WILL* require adjusting afterwards. Save config?'
959-
):
960-
dest = None
961-
while not dest:
962-
save_to = os.path.abspath(
963-
os.path.join(
964-
get_config_dir(),
965-
'%s.%s' % (sconf.get('session_name'), config_format),
966-
)
967-
)
968-
dest_prompt = click.prompt(
969-
'Path to new config:', value_proc=get_abs_path, default=save_to
970-
)
971-
if not force and os.path.exists(dest_prompt):
972-
print('%s exists. Pick a new filename.' % dest_prompt)
973-
continue
974-
975-
dest = dest_prompt
976-
977-
dest = os.path.abspath(os.path.relpath(os.path.expanduser(dest)))
978-
if click.confirm('Save to %s?' % dest):
979-
destdir = os.path.dirname(dest)
980-
if not os.path.isdir(destdir):
981-
os.makedirs(destdir)
982-
buf = open(dest, 'w')
983-
buf.write(newconfig)
984-
buf.close()
1022+
if yes or click.confirm('Save to %s?' % dest):
1023+
destdir = os.path.dirname(dest)
1024+
if not os.path.isdir(destdir):
1025+
os.makedirs(destdir)
1026+
buf = open(dest, 'w')
1027+
buf.write(newconfig)
1028+
buf.close()
9851029

1030+
if not quiet:
9861031
print('Saved to %s.' % dest)
987-
else:
988-
print(
989-
'tmuxp has examples in JSON and YAML format at '
990-
'<http://tmuxp.git-pull.com/examples.html>\n'
991-
'View tmuxp docs at <http://tmuxp.git-pull.com/>.'
992-
)
993-
sys.exit()
9941032

9951033

9961034
@cli.command(name='load', short_help='Load tmuxp workspaces.')

0 commit comments

Comments
 (0)