Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@

#### What's new

- #701: `tmuxp freeze` now accepts `--quiet` and `--yes` along with the
`--config-format` and filename (`--save-to`). This means you can do it all in
one command:

`tmuxp freeze -yqo .tmuxp.yaml`

Or bind it to `.tmux.conf` itself: `bind -T root C-s run-shell "tmuxp freeze -yqo .tmuxp.yaml"`

Credit: [@davidatbu](https://github.com/davidatbu)

- #672: Panes now accept `shell` for their initial command.

Equivalent to `tmux split-windows`'s `[shell-command]`
Expand Down
8 changes: 4 additions & 4 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -868,16 +868,16 @@ def test_import_tmuxinator(cli_args, inputs, tmpdir, monkeypatch):
@pytest.mark.parametrize(
"cli_args,inputs",
[
(['freeze', 'myfrozensession'], ['\n', 'y\n', './la.yaml\n', 'y\n']),
(['freeze', 'myfrozensession'], ['y\n', './la.yaml\n', 'y\n']),
( # Exists
['freeze', 'myfrozensession'],
['\n', 'y\n', './exists.yaml\n', './la.yaml\n', 'y\n'],
['y\n', './exists.yaml\n', './la.yaml\n', 'y\n'],
),
( # Imply current session if not entered
['freeze'],
['\n', 'y\n', './la.yaml\n', 'y\n'],
['y\n', './la.yaml\n', 'y\n'],
),
(['freeze'], ['\n', 'y\n', './exists.yaml\n', './la.yaml\n', 'y\n']), # Exists
(['freeze'], ['y\n', './exists.yaml\n', './la.yaml\n', 'y\n']), # Exists
],
)
def test_freeze(server, cli_args, inputs, tmpdir, monkeypatch):
Expand Down
130 changes: 84 additions & 46 deletions tmuxp/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -911,8 +911,33 @@ def command_shell(
@click.argument('session_name', nargs=1, required=False)
@click.option('-S', 'socket_path', help='pass-through for tmux -S')
@click.option('-L', 'socket_name', help='pass-through for tmux -L')
@click.option(
'-f',
'--config-format',
type=click.Choice(['yaml', 'json']),
help='format to save in',
)
@click.option('-o', '--save-to', type=click.Path(exists=False), help='file to save to')
@click.option(
'-y',
'--yes',
type=bool,
is_flag=True,
default=False,
help="Don't prompt for confirmation",
)
@click.option(
'-q',
'--quiet',
type=bool,
is_flag=True,
default=False,
help="Don't prompt for confirmation",
)
@click.option('--force', 'force', help='overwrite the config file', is_flag=True)
def command_freeze(session_name, socket_name, socket_path, force):
def command_freeze(
session_name, socket_name, config_format, save_to, socket_path, yes, quiet, force
):
"""Snapshot a session into a config.

If SESSION_NAME is provided, snapshot that session. Otherwise, use the
Expand All @@ -936,61 +961,74 @@ def command_freeze(session_name, socket_name, socket_path, force):
configparser = kaptan.Kaptan()
newconfig = config.inline(sconf)
configparser.import_config(newconfig)
config_format = click.prompt(
'Convert to', value_proc=_validate_choices(['yaml', 'json']), default='yaml'
)

if not quiet:
print(
'---------------------------------------------------------------'
'\n'
'Freeze does its best to snapshot live tmux sessions.\n'
)
if not (
yes
or click.confirm(
'The new config *WILL* require adjusting afterwards. Save config?'
)
):
if not quiet:
print(
'tmuxp has examples in JSON and YAML format at '
'<http://tmuxp.git-pull.com/examples.html>\n'
'View tmuxp docs at <http://tmuxp.git-pull.com/>.'
)
sys.exit()

dest = save_to
while not dest:
save_to = os.path.abspath(
os.path.join(
get_config_dir(),
'%s.%s' % (sconf.get('session_name'), config_format or 'yaml'),
)
)
dest_prompt = click.prompt(
'Save to: %s' % save_to, value_proc=get_abs_path, default=save_to
)
if not force and os.path.exists(dest_prompt):
print('%s exists. Pick a new filename.' % dest_prompt)
continue

dest = dest_prompt
dest = os.path.abspath(os.path.relpath(os.path.expanduser(dest)))

if config_format is None:
valid_config_formats = ['json', 'yaml']
_, config_format = os.path.splitext(dest)
config_format = config_format[1:].lower()
if config_format not in valid_config_formats:
config_format = click.prompt(
"Couldn't ascertain one of [%s] from file name. Convert to"
% ", ".join(valid_config_formats),
value_proc=_validate_choices(['yaml', 'json']),
default='yaml',
)

if config_format == 'yaml':
newconfig = configparser.export(
'yaml', indent=2, default_flow_style=False, safe=True
)
elif config_format == 'json':
newconfig = configparser.export('json', indent=2)
else:
sys.exit('Unknown config format.')

print(
'---------------------------------------------------------------'
'\n'
'Freeze does its best to snapshot live tmux sessions.\n'
)
if click.confirm(
'The new config *WILL* require adjusting afterwards. Save config?'
):
dest = None
while not dest:
save_to = os.path.abspath(
os.path.join(
get_config_dir(),
'%s.%s' % (sconf.get('session_name'), config_format),
)
)
dest_prompt = click.prompt(
'Path to new config:', value_proc=get_abs_path, default=save_to
)
if not force and os.path.exists(dest_prompt):
print('%s exists. Pick a new filename.' % dest_prompt)
continue

dest = dest_prompt

dest = os.path.abspath(os.path.relpath(os.path.expanduser(dest)))
if click.confirm('Save to %s?' % dest):
destdir = os.path.dirname(dest)
if not os.path.isdir(destdir):
os.makedirs(destdir)
buf = open(dest, 'w')
buf.write(newconfig)
buf.close()
if yes or click.confirm('Save to %s?' % dest):
destdir = os.path.dirname(dest)
if not os.path.isdir(destdir):
os.makedirs(destdir)
buf = open(dest, 'w')
buf.write(newconfig)
buf.close()

if not quiet:
print('Saved to %s.' % dest)
else:
print(
'tmuxp has examples in JSON and YAML format at '
'<http://tmuxp.git-pull.com/examples.html>\n'
'View tmuxp docs at <http://tmuxp.git-pull.com/>.'
)
sys.exit()


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