widgets.remote: retain focus when showing remote messages
[git-cola.git] / cola / interaction.py
bloba8135c142c3dd96284beec043c7d244bb7a53a7b
1 import os
2 import sys
4 from . import core
5 from .i18n import N_
8 # The dependency injection calls to install() in ColaApplication's constructor
9 # triggers method-already-defined pylint warnings. Silence that warning.
11 # pylint: disable=function-redefined
12 class Interaction:
13 """Prompts the user and answers questions"""
15 VERBOSE = bool(os.getenv('GIT_COLA_VERBOSE'))
17 @classmethod
18 def command(cls, title, cmd, status, out, err):
19 """Log a command and display error messages on failure"""
20 cls.log_status(status, out, err)
21 if status != 0:
22 cls.command_error(title, cmd, status, out, err)
24 @classmethod
25 def command_error(cls, title, cmd, status, out, err):
26 """Display an error message for a failed command"""
27 core.print_stderr(title)
28 core.print_stderr('-' * len(title))
29 core.print_stderr(cls.format_command_status(cmd, status))
30 core.print_stdout('')
31 if out:
32 core.print_stdout(out)
33 if err:
34 core.print_stderr(err)
36 @staticmethod
37 def format_command_status(cmd, status):
38 return N_('"%(command)s" returned exit status %(status)d') % {
39 'command': cmd,
40 '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,
90 cancel_text = cancel_text or 'Cancel'
91 icon = icon or '?'
93 cls.information(title, message=text, informative_text=informative_text)
94 if default:
95 prompt = '%s? [Y/n] ' % ok_text
96 else:
97 prompt = '%s? [y/N] ' % ok_text
98 sys.stdout.write(prompt)
99 sys.stdout.flush()
100 answer = sys.stdin.readline().strip()
101 if answer:
102 result = answer.lower().startswith('y')
103 else:
104 result = default
105 return result
107 @classmethod
108 def question(cls, title, message, default=True):
109 return cls.confirm(title, message, '', ok_text=N_('Continue'), default=default)
111 @classmethod
112 def run_command(cls, title, cmd):
113 cls.log('# ' + title)
114 cls.log('$ ' + core.list2cmdline(cmd))
115 status, out, err = core.run_command(cmd)
116 cls.log_status(status, out, err)
117 return status, out, err
119 @classmethod
120 def confirm_config_action(cls, _context, name, _opts):
121 return cls.confirm(
122 N_('Run %s?') % name,
123 N_('Run the "%s" command?') % name,
125 ok_text=N_('Run'),
128 @classmethod
129 def log_status(cls, status, out, err=None):
130 msg = ((out + '\n') if out else '') + ((err + '\n') if err else '')
131 cls.log(msg)
132 cls.log('exit status %s' % status)
134 @classmethod
135 def log(cls, message):
136 if cls.VERBOSE:
137 core.print_stdout(message)
139 @classmethod
140 def save_as(cls, filename, title):
141 if cls.confirm(title, 'Save as %s?' % filename, '', ok_text='Save'):
142 return filename
143 return None
145 @staticmethod
146 def async_command(title, command, runtask):
147 pass
149 @classmethod
150 def choose_ref(cls, _context, title, button_text, default=None, icon=None):
151 icon = icon or '?'
152 cls.information(title, button_text)
153 return sys.stdin.readline().strip() or default