Merge lp:~chromakode/boots/boots_pager into lp:~cboylan/boots/boots_pager

Proposed by Max Goodhart
Status: Merged
Merged at revision: not available
Proposed branch: lp:~chromakode/boots/boots_pager
Merge into: lp:~cboylan/boots/boots_pager
Diff against target: 129 lines (+62/-16)
2 files modified
boots/app/client_config.py (+32/-1)
boots/lib/ui/plain.py (+30/-15)
To merge this branch: bzr merge lp:~chromakode/boots/boots_pager
Reviewer Review Type Date Requested Status
Boots Developers Pending
Review via email: mp+20354@code.launchpad.net
To post a comment you must log in.
lp:~chromakode/boots/boots_pager updated
101. By Max Goodhart

Fix handling of IOError in pager invocation.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'boots/app/client_config.py'
--- boots/app/client_config.py 2010-02-28 21:48:22 +0000
+++ boots/app/client_config.py 2010-03-01 08:21:16 +0000
@@ -26,9 +26,31 @@
26options/arguments."""26options/arguments."""
2727
28import optparse28import optparse
29import os29import os, os.path
30import info30import info
3131
32def find_executable(name):
33 # Search algorithm adapted from os._execvpe
34 head, tail = os.path.split(name)
35 if head and os.path.exists(name):
36 return name
37 else:
38 if 'PATH' in os.environ:
39 envpath = os.environ['PATH']
40 else:
41 envpath = os.defpath
42 PATH = envpath.split(os.pathsep)
43 for dir in PATH:
44 fullname = os.path.join(dir, name)
45 if os.path.exists(fullname):
46 return fullname
47
48def get_auto_pager():
49 if find_executable("less"):
50 return "less -XF"
51 elif find_executable("more"):
52 return "more"
53
32class ClientConfig(object):54class ClientConfig(object):
33 """Class used to read client configuration from files and the cli."""55 """Class used to read client configuration from files and the cli."""
3456
@@ -50,6 +72,7 @@
50 "prompt1": "> ",72 "prompt1": "> ",
51 "prompt2": "+ ",73 "prompt2": "+ ",
52 "pager": None,74 "pager": None,
75 "pager_command": None,
53 "terminating_char": ";",76 "terminating_char": ";",
54 "history_length": 100,77 "history_length": 100,
55 "history_file": os.path.expanduser("~/.boots_history")}78 "history_file": os.path.expanduser("~/.boots_history")}
@@ -160,6 +183,14 @@
160 183
161 self._dict.update(from_file)184 self._dict.update(from_file)
162 self._dict.update(from_cli)185 self._dict.update(from_cli)
186 self._interpret_options()
187
188 def _interpret_options(self):
189 # Interpret options
190 if self["pager"] == "auto":
191 self["pager_command"] = get_auto_pager()
192 elif self["pager"]:
193 self["pager_command"] = self["pager"]
163194
164 def get_file_conf(self, filepath):195 def get_file_conf(self, filepath):
165 """Read a configuration from the specified file. Return a dict."""196 """Read a configuration from the specified file. Return a dict."""
166197
=== modified file 'boots/lib/ui/plain.py'
--- boots/lib/ui/plain.py 2010-03-01 07:07:41 +0000
+++ boots/lib/ui/plain.py 2010-03-01 08:21:16 +0000
@@ -61,10 +61,7 @@
61 self.prompt2 = console.config["prompt2"]61 self.prompt2 = console.config["prompt2"]
62 self.hist_file = console.config["history_file"]62 self.hist_file = console.config["history_file"]
63 self.lingo = console.config["lingo"]63 self.lingo = console.config["lingo"]
64 if console.config["pager"] == "auto":64 self.pager_command = console.config["pager_command"]
65 self.pager = "less -FX"
66 else:
67 self.pager = console.config["pager"]
68 self.last_desc = None65 self.last_desc = None
69 self.buffer = []66 self.buffer = []
70 67
@@ -129,6 +126,25 @@
129 self.prompt1 = prompt1126 self.prompt1 = prompt1
130 self.prompt2 = prompt2127 self.prompt2 = prompt2
131128
129 def print_with_pager(self, text):
130 try:
131 pager = subprocess.Popen(self.pager_command.split(),
132 shell=False,
133 stdin=subprocess.PIPE)
134 except:
135 sys.stdout.write("Unable to run pager command \"{0}\". Pager disabled.\n"
136 .format(self.pager_command))
137 self.pager_command = None
138 return False
139
140 try:
141 pager.communicate(text)
142 except IOError:
143 # IOError is raised sometimes with large outputs
144 pass
145
146 return True
147
132 def present(self, result):148 def present(self, result):
133 """Print the result provided as an argument.149 """Print the result provided as an argument.
134150
@@ -167,17 +183,16 @@
167 self.last_desc = result["info"]183 self.last_desc = result["info"]
168 if result["result"]:184 if result["result"]:
169 self.buffer.extend(result["result"])185 self.buffer.extend(result["result"])
170 elif self.buffer and self.pager is None:186 elif self.buffer:
171 for row in _gen_table():187 printed = False
172 sys.stdout.write(row)188 if self.pager_command and self.console.driver.is_interactive:
173 # Reset values for next result set.189 printed = self.print_with_pager("".join(_gen_table()))
174 self.buffer = []190
175 elif self.buffer and self.pager is not None and self.console.driver.is_interactive:191 # Fallback if no pager set, or paging fails.
176 pager = subprocess.Popen(self.pager.split(), shell=False, stdin=subprocess.PIPE)192 if not printed:
177 try:193 for row in _gen_table():
178 pager.communicate("".join(_gen_table()))194 sys.stdout.write(row)
179 except IOError:195
180 pass
181 # Reset values for next result set.196 # Reset values for next result set.
182 self.buffer = []197 self.buffer = []
183 elif isinstance(result, Exception):198 elif isinstance(result, Exception):

Subscribers

People subscribed via source and target branches

to all changes: