Repository: pre-commit/pre-commit
Pull request #408 (2016-09-01 00:17:32)

Use 80 or min width instead of terminal size
This would factor out pyterminalsize and instead use 80 as a default width and expand if the hook names are long.


Patch:
diff --git a/pre_commit/commands/run.py b/pre_commit/commands/run.py
index 424e295..1645ad4 100644
--- a/pre_commit/commands/run.py
+++ b/pre_commit/commands/run.py
@@ -30,25 +30,6 @@ def _hook_msg_start(hook, verbose):
     )
 
 
-def _print_no_files_skipped(hook, write, args):
-    write(get_hook_message(
-        _hook_msg_start(hook, args.verbose),
-        postfix='(no files to check) ',
-        end_msg='Skipped',
-        end_color=color.TURQUOISE,
-        use_color=args.color,
-    ))
-
-
-def _print_user_skipped(hook, write, args):
-    write(get_hook_message(
-        _hook_msg_start(hook, args.verbose),
-        end_msg='Skipped',
-        end_color=color.YELLOW,
-        use_color=args.color,
-    ))
-
-
 def get_changed_files(new, old):
     return cmd_output(
         'git', 'diff', '--name-only', '{0}...{1}'.format(old, new),
@@ -71,18 +52,37 @@ def get_filenames(args, include_expr, exclude_expr):
     return getter(include_expr, exclude_expr)
 
 
-def _run_single_hook(hook, repo, args, write, skips=frozenset()):
+SKIPPED = 'Skipped'
+NO_FILES = '(no files to check)'
+
+
+def _run_single_hook(hook, repo, args, write, skips, cols):
     filenames = get_filenames(args, hook['files'], hook['exclude'])
     if hook['id'] in skips:
-        _print_user_skipped(hook, write, args)
+        write(get_hook_message(
+            _hook_msg_start(hook, args.verbose),
+            end_msg=SKIPPED,
+            end_color=color.YELLOW,
+            use_color=args.color,
+            cols=cols,
+        ))
         return 0
     elif not filenames and not hook['always_run']:
-        _print_no_files_skipped(hook, write, args)
+        write(get_hook_message(
+            _hook_msg_start(hook, args.verbose),
+            postfix=NO_FILES,
+            end_msg=SKIPPED,
+            end_color=color.TURQUOISE,
+            use_color=args.color,
+            cols=cols,
+        ))
         return 0
 
     # Print the hook and the dots first in case the hook takes hella long to
     # run.
-    write(get_hook_message(_hook_msg_start(hook, args.verbose), end_len=6))
+    write(get_hook_message(
+        _hook_msg_start(hook, args.verbose), end_len=6, cols=cols,
+    ))
     sys.stdout.flush()
 
     diff_before = cmd_output('git', 'diff', retcode=None, encoding=None)
@@ -128,12 +128,32 @@ def _run_single_hook(hook, repo, args, write, skips=frozenset()):
     return retcode
 
 
+def _compute_cols(hooks, verbose):
+    """Compute the number of columns to display hook messages.  The widest
+    that will be displayed is in the no files skipped case:
+
+        Hook name...(no files to check) Skipped
+
+    or in the verbose case
+
+        Hook name [hookid]...(no files to check) Skipped
+    """
+    if hooks:
+        name_len = max(len(_hook_msg_start(hook, verbose)) for hook in hooks)
+    else:
+        name_len = 0
+
+    cols = name_len + 3 + len(NO_FILES) + 1 + len(SKIPPED)
+    return max(cols, 80)
+
+
 def _run_hooks(repo_hooks, args, write, environ):
     """Actually run the hooks."""
     skips = _get_skips(environ)
+    cols = _compute_cols([hook for _, hook in repo_hooks], args.verbose)
     retval = 0
     for repo, hook in repo_hooks:
-        retval |= _run_single_hook(hook, repo, args, write, skips)
+        retval |= _run_single_hook(hook, repo, args, write, skips, cols)
     return retval
 
 
diff --git a/pre_commit/output.py b/pre_commit/output.py
index 4d829bf..eb7fbb8 100644
--- a/pre_commit/output.py
+++ b/pre_commit/output.py
@@ -2,15 +2,10 @@ from __future__ import unicode_literals
 
 import sys
 
-from pyterminalsize import get_terminal_size
-
 from pre_commit import color
 from pre_commit import five
 
 
-COLS = get_terminal_size((80, 0)).columns
-
-
 def get_hook_message(
         start,
         postfix='',
@@ -18,7 +13,7 @@ def get_hook_message(
         end_len=0,
         end_color=None,
         use_color=None,
-        cols=COLS,
+        cols=80,
 ):
     """Prints a message for running a hook.
 
diff --git a/setup.py b/setup.py
index 7de2d33..e775511 100644
--- a/setup.py
+++ b/setup.py
@@ -41,7 +41,6 @@ setup(
         'cached-property',
         'jsonschema',
         'nodeenv>=0.11.1',
-        'pyterminalsize',
         'pyyaml',
         'virtualenv',
     ],


Test patch:
diff --git a/tests/commands/run_test.py b/tests/commands/run_test.py
index ae8b523..309575f 100644
--- a/tests/commands/run_test.py
+++ b/tests/commands/run_test.py
@@ -13,6 +13,7 @@ import pytest
 
 import pre_commit.constants as C
 from pre_commit.commands.install_uninstall import install
+from pre_commit.commands.run import _compute_cols
 from pre_commit.commands.run import _get_skips
 from pre_commit.commands.run import _has_unmerged_paths
 from pre_commit.commands.run import get_changed_files
@@ -279,6 +280,23 @@ def test_merge_conflict_resolved(in_merge_conflict, mock_out_store_directory):
         assert msg in printed
 
 
+@pytest.mark.parametrize(
+    ('hooks', 'verbose', 'expected'),
+    (
+        ([], True, 80),
+        ([{'id': 'a', 'name': 'a' * 51}], False, 81),
+        ([{'id': 'a', 'name': 'a' * 51}], True, 85),
+        (
+            [{'id': 'a', 'name': 'a' * 51}, {'id': 'b', 'name': 'b' * 52}],
+            False,
+            82,
+        ),
+    ),
+)
+def test_compute_cols(hooks, verbose, expected):
+    assert _compute_cols(hooks, verbose) == expected
+
+
 @pytest.mark.parametrize(
     ('environ', 'expected_output'),
     (