qtutils: simplify the BlockSignals implementation
[git-cola.git] / cola / interaction.py
blob4ca7ac487da4c28e26ed4fb0b3530c0448d7c4cc
1 from __future__ import division, absolute_import, unicode_literals
2 import os
3 import sys
5 from . import core
6 from .i18n import N_
9 # The dependency injection calls to install() in ColaApplication's constructor
10 # triggers method-already-defined pylint warnings. Silence that warning.
12 # pylint: disable=function-redefined
13 class Interaction(object):
14 """Prompts the user and answers questions"""
16 VERBOSE = bool(os.getenv('GIT_COLA_VERBOSE'))
18 @classmethod
19 def command(cls, title, cmd, status, out, err):
20 """Log a command and display error messages on failure"""
21 cls.log_status(status, out, err)
22 if status != 0:
23 cls.command_error(title, cmd, status, out, err)
25 @classmethod
26 def command_error(cls, title, cmd, status, out, err):
27 """Display an error message for a failed command"""
28 core.print_stderr(title)
29 core.print_stderr('-' * len(title))
30 core.print_stderr(cls.format_command_status(cmd, status))
31 core.print_stdout('')
32 if out:
33 core.print_stdout(out)
34 if err:
35 core.print_stderr(err)
37 @staticmethod
38 def format_command_status(cmd, status):
39 return N_('"%(command)s" returned exit status %(status)d') % dict(
40 command=cmd, status=status
43 @staticmethod
44 def format_out_err(out, err):
45 """Format stdout and stderr into a single string"""
46 details = out or ''
47 if err:
48 if details and not details.endswith('\n'):
49 details += '\n'
50 details += err
51 return details
53 @staticmethod
54 def information(title, message=None, details=None, informative_text=None):
55 if message is None:
56 message = title
57 scope = {}
58 scope['title'] = title
59 scope['title_dashes'] = '-' * len(title)
60 scope['message'] = message
61 scope['details'] = ('\n' + details) if details else ''
62 scope['informative_text'] = (
63 ('\n' + informative_text) if informative_text else ''
65 sys.stdout.write(
66 """
67 %(title)s
68 %(title_dashes)s
69 %(message)s%(informative_text)s%(details)s\n"""
70 % scope
72 sys.stdout.flush()
74 @classmethod
75 def critical(cls, title, message=None, details=None):
76 """Show a warning with the provided title and message."""
77 cls.information(title, message=message, details=details)
79 @classmethod
80 def confirm(
81 cls,
82 title,
83 text,
84 informative_text,
85 ok_text,
86 icon=None,
87 default=True,
88 cancel_text=None,
91 cancel_text = cancel_text or 'Cancel'
92 icon = icon or '?'
94 cls.information(title, message=text, informative_text=informative_text)
95 if default:
96 prompt = '%s? [Y/n] ' % ok_text
97 else:
98 prompt = '%s? [y/N] ' % ok_text
99 sys.stdout.write(prompt)
100 sys.stdout.flush()
101 answer = sys.stdin.readline().strip()
102 if answer:
103 result = answer.lower().startswith('y')
104 else:
105 result = default
106 return result
108 @classmethod
109 def question(cls, title, message, default=True):
110 return cls.confirm(title, message, '', ok_text=N_('Continue'), default=default)
112 @classmethod
113 def run_command(cls, title, cmd):
114 cls.log('# ' + title)
115 cls.log('$ ' + core.list2cmdline(cmd))
116 status, out, err = core.run_command(cmd)
117 cls.log_status(status, out, err)
118 return status, out, err
120 @classmethod
121 def confirm_config_action(cls, _context, name, _opts):
122 return cls.confirm(
123 N_('Run %s?') % name,
124 N_('Run the "%s" command?') % name,
126 ok_text=N_('Run'),
129 @classmethod
130 def log_status(cls, status, out, err=None):
131 msg = ((out + '\n') if out else '') + ((err + '\n') if err else '')
132 cls.log(msg)
133 cls.log('exit status %s' % status)
135 @classmethod
136 def log(cls, message):
137 if cls.VERBOSE:
138 core.print_stdout(message)
140 @classmethod
141 def save_as(cls, filename, title):
142 if cls.confirm(title, 'Save as %s?' % filename, '', ok_text='Save'):
143 return filename
144 return None
146 @staticmethod
147 def async_command(title, command, runtask):
148 pass
150 @classmethod
151 def choose_ref(cls, _context, title, button_text, default=None, icon=None):
152 icon = icon or '?'
153 cls.information(title, button_text)
154 return sys.stdin.readline().strip() or default