Skip to content

Commit 21b4639

Browse files
authored
load: Add --log-file, rename tmuxp --log_level to --log-level (#647)
2 parents 8858179 + 287fcc1 commit 21b4639

File tree

9 files changed

+148
-64
lines changed

9 files changed

+148
-64
lines changed

.github/workflows/tests.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ jobs:
2929
run: |
3030
curl -O -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py
3131
python get-poetry.py -y --version 1.0.10
32-
echo "::set-env name=PATH::$HOME/.poetry/bin:$PATH"
32+
echo "PATH=${HOME}/.poetry/bin:${PATH}" >> $GITHUB_ENV
3333
rm get-poetry.py
3434
3535
- name: Get poetry cache paths from config
3636
run: |
37-
echo ::set-env name=poetry_cache_dir::$(poetry config --list | sed -n 's/.*cache-dir = //p' | sed -e 's/^"//' -e 's/"$//')
38-
echo ::set-env name=poetry_virtualenvs_path::$(poetry config --list | sed -n 's/.*virtualenvs.path = .* # //p' | sed -e 's/^"//' -e 's/"$//')
37+
echo "poetry_cache_dir=$(poetry config --list | sed -n 's/.*cache-dir = //p' | sed -e 's/^\"//' -e 's/\"$//')" >> $GITHUB_ENV
38+
echo "poetry_virtualenvs_path=$(poetry config --list | sed -n 's/.*virtualenvs.path = .* # //p' | sed -e 's/^\"//' -e 's/\"$//')" >> $GITHUB_ENV
3939
4040
- name: Configure poetry
4141
shell: bash

CHANGES

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Here you can find the recent changes to tmuxp
66

77
current
88
-------
9+
- Adding option to dump `load` output to log file
910
- *Insert changes/features/fixes for next release here*
1011

1112
tmuxp 1.6.2 (2020-11-08)

README.rst

+9-1
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,16 @@ You can auto confirm the prompt. In this case no preview will be shown.
177177
$ tmuxp convert --yes filename
178178
179179
180-
Debug Info
180+
Debugging Helpers
181181
----------
182182
183+
The `load` command provides a way to log output to a log file for debugging
184+
purposes.
185+
186+
.. code-block:: sh
187+
188+
$ tmuxp load --log-file <log-file-name> .
189+
183190
Collect system info to submit with a Github issue:
184191
185192
.. code-block:: sh
@@ -192,6 +199,7 @@ Collect system info to submit with a Github issue:
192199
193200
# ... so on
194201
202+
195203
Docs / Reading material
196204
-----------------------
197205

docs/cli.rst

+12-1
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,23 @@ are created, the last session is named from the terminal.
184184
185185
$ tmxup load -s <new_session_name> <filename1> ...
186186
187+
The output of the ``load`` command can be logged to a file for
188+
debugging purposes. the log level can be controlled with the global
189+
``--log-level`` option (defaults to INFO).
190+
191+
.. code-block:: bash
192+
193+
$ tmuxp load <filename> --log-file <log_filename>
194+
$ tmuxp --log-level <LEVEL> load <filename> --log-file <log_filename>
195+
196+
187197
.. _cli_debug_info:
188198

189199
Debug Info
190200
----------
191201

192-
Use to collect all relevant information for submitting an issue to the project.
202+
Use to collect all relevant information for submitting an issue to
203+
the project.
193204

194205
.. code-block:: bash
195206

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ skip-string-normalization = true
33

44
[tool.poetry]
55
name = "tmuxp"
6-
version = "1.6.2"
6+
version = "1.6.3"
77
description = "tmux session manager"
88
license = "MIT"
99
authors = ["Tony Narlock <[email protected]>"]

tests/test_cli.py

+27
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,33 @@ def test_load_zsh_autotitle_warning(cli_args, tmpdir, monkeypatch):
408408
assert 'Please set' not in result.output
409409

410410

411+
@pytest.mark.parametrize(
412+
"cli_args",
413+
[
414+
(['load', '.', '--log-file', 'log.txt']),
415+
],
416+
)
417+
def test_load_log_file(cli_args, tmpdir, monkeypatch):
418+
# create dummy tmuxp yaml that breaks to prevent actually loading tmux
419+
tmpdir.join('.tmuxp.yaml').write(
420+
"""
421+
session_name: hello
422+
"""
423+
)
424+
tmpdir.join('.oh-my-zsh').ensure(dir=True)
425+
monkeypatch.setenv('HOME', str(tmpdir))
426+
427+
with tmpdir.as_cwd():
428+
print('tmpdir: {0}'.format(tmpdir))
429+
runner = CliRunner()
430+
431+
# If autoconfirm (-y) no need to prompt y
432+
input_args = 'y\ny\n' if '-y' not in cli_args else ''
433+
434+
runner.invoke(cli.cli, cli_args, input=input_args)
435+
assert 'Loading' in tmpdir.join('log.txt').open().read()
436+
437+
411438
@pytest.mark.parametrize("cli_cmd", ['shell', ('shell', '--pdb')])
412439
@pytest.mark.parametrize(
413440
"cli_args,inputs,env,expected_output",

tmuxp/__about__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
__title__ = 'tmuxp'
22
__package_name__ = 'tmuxp'
3-
__version__ = '1.6.2'
3+
__version__ = '1.6.3'
44
__description__ = 'tmux session manager'
55
__email__ = '[email protected]'
66
__author__ = 'Tony Narlock'

tmuxp/cli.py

+50-29
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,18 @@ def get_cwd():
4242
return os.getcwd()
4343

4444

45+
def tmuxp_echo(message=None, log_level='INFO', style_log=False, **click_kwargs):
46+
"""
47+
Combines logging.log and click.echo
48+
"""
49+
if style_log:
50+
logger.log(log.LOG_LEVELS[log_level], message)
51+
else:
52+
logger.log(log.LOG_LEVELS[log_level], click.unstyle(message))
53+
54+
click.echo(message, **click_kwargs)
55+
56+
4557
def get_config_dir():
4658
"""
4759
Return tmuxp configuration directory.
@@ -246,8 +258,8 @@ def scan_config_argument(ctx, param, value, config_dir=None):
246258
config_dir = config_dir()
247259

248260
if not config:
249-
click.echo("Enter at least one CONFIG")
250-
click.echo(ctx.get_help(), color=ctx.color)
261+
tmuxp_echo("Enter at least one CONFIG")
262+
tmuxp_echo(ctx.get_help(), color=ctx.color)
251263
ctx.exit()
252264

253265
if isinstance(value, string_types):
@@ -357,11 +369,14 @@ def scan_config(config, config_dir=None):
357369
]
358370

359371
if len(candidates) > 1:
360-
click.secho(
361-
'Multiple .tmuxp.{yml,yaml,json} configs in %s' % dirname(config),
362-
fg="red",
372+
tmuxp_echo(
373+
click.style(
374+
'Multiple .tmuxp.{yml,yaml,json} configs in %s'
375+
% dirname(config),
376+
fg="red",
377+
)
363378
)
364-
click.echo(
379+
tmuxp_echo(
365380
click.wrap_text(
366381
'This is undefined behavior, use only one. '
367382
'Use file names e.g. myproject.json, coolproject.yaml. '
@@ -505,6 +520,11 @@ def load_workspace(
505520
# get the canonical path, eliminating any symlinks
506521
config_file = os.path.realpath(config_file)
507522

523+
tmuxp_echo(
524+
click.style('[Loading] ', fg='green')
525+
+ click.style(config_file, fg='blue', bold=True)
526+
)
527+
508528
# kaptan allows us to open a yaml or json file as a dict
509529
sconfig = kaptan.Kaptan()
510530
sconfig = sconfig.import_config(config_file).get()
@@ -525,7 +545,7 @@ def load_workspace(
525545
try: # load WorkspaceBuilder object for tmuxp config / tmux server
526546
builder = WorkspaceBuilder(sconf=sconfig, server=t)
527547
except exc.EmptyConfigException:
528-
click.echo('%s is empty or parsed no config data' % config_file, err=True)
548+
tmuxp_echo('%s is empty or parsed no config data' % config_file, err=True)
529549
return
530550

531551
session_name = sconfig['session_name']
@@ -545,11 +565,6 @@ def load_workspace(
545565
return
546566

547567
try:
548-
click.echo(
549-
click.style('[Loading] ', fg='green')
550-
+ click.style(config_file, fg='blue', bold=True)
551-
)
552-
553568
builder.build() # load tmux session via workspace builder
554569

555570
if 'TMUX' in os.environ: # tmuxp ran from inside tmux
@@ -586,8 +601,8 @@ def load_workspace(
586601
except exc.TmuxpException as e:
587602
import traceback
588603

589-
click.echo(traceback.format_exc(), err=True)
590-
click.echo(e, err=True)
604+
tmuxp_echo(traceback.format_exc(), err=True)
605+
tmuxp_echo(e, err=True)
591606

592607
choice = click.prompt(
593608
'Error loading workspace. (k)ill, (a)ttach, (d)etach?',
@@ -597,7 +612,7 @@ def load_workspace(
597612

598613
if choice == 'k':
599614
builder.session.kill_session()
600-
click.echo('Session killed.')
615+
tmuxp_echo('Session killed.')
601616
elif choice == 'a':
602617
if 'TMUX' in os.environ:
603618
builder.session.switch_client()
@@ -612,7 +627,7 @@ def load_workspace(
612627
@click.group(context_settings={'obj': {}})
613628
@click.version_option(__version__, '-V', '--version', message='%(prog)s %(version)s')
614629
@click.option(
615-
'--log_level',
630+
'--log-level',
616631
default='INFO',
617632
help='Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)',
618633
)
@@ -625,12 +640,12 @@ def cli(log_level):
625640
try:
626641
has_minimum_version()
627642
except TmuxCommandNotFound:
628-
click.echo('tmux not found. tmuxp requires you install tmux first.')
643+
tmuxp_echo('tmux not found. tmuxp requires you install tmux first.')
629644
sys.exit()
630645
except exc.TmuxpException as e:
631-
click.echo(e, err=True)
646+
tmuxp_echo(e, err=True)
632647
sys.exit()
633-
setup_logger(level=log_level.upper())
648+
setup_logger(logger=logger, level=log_level.upper())
634649

635650

636651
def setup_logger(logger=None, level='INFO'):
@@ -649,12 +664,12 @@ def setup_logger(logger=None, level='INFO'):
649664
logger = logging.getLogger()
650665

651666
if not logger.handlers: # setup logger handlers
652-
channel = logging.StreamHandler()
653-
channel.setFormatter(log.DebugLogFormatter())
654-
667+
# channel = logging.StreamHandler()
668+
# channel.setFormatter(log.DebugLogFormatter())
655669
# channel.setFormatter(log.LogFormatter())
670+
656671
logger.setLevel(level)
657-
logger.addHandler(channel)
672+
# logger.addHandler(channel)
658673

659674

660675
def startup(config_dir):
@@ -875,6 +890,7 @@ def command_freeze(session_name, socket_name, socket_path, force):
875890
flag_value=88,
876891
help='Like -2, but indicates that the terminal supports 88 colours.',
877892
)
893+
@click.option('--log-file', help='File to log errors/output to')
878894
def command_load(
879895
ctx,
880896
config,
@@ -884,6 +900,7 @@ def command_load(
884900
answer_yes,
885901
detached,
886902
colors,
903+
log_file,
887904
):
888905
"""Load a tmux workspace from each CONFIG.
889906
@@ -908,6 +925,10 @@ def command_load(
908925
detached mode.
909926
"""
910927
util.oh_my_zsh_auto_title()
928+
if log_file:
929+
logfile_handler = logging.FileHandler(log_file)
930+
logfile_handler.setFormatter(log.LogFormatter())
931+
logger.addHandler(logfile_handler)
911932

912933
tmux_options = {
913934
'socket_name': socket_name,
@@ -919,8 +940,8 @@ def command_load(
919940
}
920941

921942
if not config:
922-
click.echo("Enter at least one CONFIG")
923-
click.echo(ctx.get_help(), color=ctx.color)
943+
tmuxp_echo("Enter at least one CONFIG")
944+
tmuxp_echo(ctx.get_help(), color=ctx.color)
924945
ctx.exit()
925946

926947
if isinstance(config, string_types):
@@ -962,7 +983,7 @@ def import_config(configfile, importfunc):
962983
else:
963984
sys.exit('Unknown config format.')
964985

965-
click.echo(
986+
tmuxp_echo(
966987
newconfig + '---------------------------------------------------------------'
967988
'\n'
968989
'Configuration import does its best to convert files.\n'
@@ -984,9 +1005,9 @@ def import_config(configfile, importfunc):
9841005
buf.write(newconfig)
9851006
buf.close()
9861007

987-
click.echo('Saved to %s.' % dest)
1008+
tmuxp_echo('Saved to %s.' % dest)
9881009
else:
989-
click.echo(
1010+
tmuxp_echo(
9901011
'tmuxp has examples in JSON and YAML format at '
9911012
'<http://tmuxp.git-pull.com/examples.html>\n'
9921013
'View tmuxp docs at <http://tmuxp.git-pull.com/>'
@@ -1125,4 +1146,4 @@ def format_tmux_resp(std_resp):
11251146
% format_tmux_resp(tmux_cmd('show-window-options', '-g')),
11261147
]
11271148

1128-
click.echo('\n'.join(output))
1149+
tmuxp_echo('\n'.join(output))

0 commit comments

Comments
 (0)