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
1=== modified file 'boots/app/client_config.py'
2--- boots/app/client_config.py 2010-02-28 21:48:22 +0000
3+++ boots/app/client_config.py 2010-03-01 08:21:16 +0000
4@@ -26,9 +26,31 @@
5 options/arguments."""
6
7 import optparse
8-import os
9+import os, os.path
10 import info
11
12+def find_executable(name):
13+ # Search algorithm adapted from os._execvpe
14+ head, tail = os.path.split(name)
15+ if head and os.path.exists(name):
16+ return name
17+ else:
18+ if 'PATH' in os.environ:
19+ envpath = os.environ['PATH']
20+ else:
21+ envpath = os.defpath
22+ PATH = envpath.split(os.pathsep)
23+ for dir in PATH:
24+ fullname = os.path.join(dir, name)
25+ if os.path.exists(fullname):
26+ return fullname
27+
28+def get_auto_pager():
29+ if find_executable("less"):
30+ return "less -XF"
31+ elif find_executable("more"):
32+ return "more"
33+
34 class ClientConfig(object):
35 """Class used to read client configuration from files and the cli."""
36
37@@ -50,6 +72,7 @@
38 "prompt1": "> ",
39 "prompt2": "+ ",
40 "pager": None,
41+ "pager_command": None,
42 "terminating_char": ";",
43 "history_length": 100,
44 "history_file": os.path.expanduser("~/.boots_history")}
45@@ -160,6 +183,14 @@
46
47 self._dict.update(from_file)
48 self._dict.update(from_cli)
49+ self._interpret_options()
50+
51+ def _interpret_options(self):
52+ # Interpret options
53+ if self["pager"] == "auto":
54+ self["pager_command"] = get_auto_pager()
55+ elif self["pager"]:
56+ self["pager_command"] = self["pager"]
57
58 def get_file_conf(self, filepath):
59 """Read a configuration from the specified file. Return a dict."""
60
61=== modified file 'boots/lib/ui/plain.py'
62--- boots/lib/ui/plain.py 2010-03-01 07:07:41 +0000
63+++ boots/lib/ui/plain.py 2010-03-01 08:21:16 +0000
64@@ -61,10 +61,7 @@
65 self.prompt2 = console.config["prompt2"]
66 self.hist_file = console.config["history_file"]
67 self.lingo = console.config["lingo"]
68- if console.config["pager"] == "auto":
69- self.pager = "less -FX"
70- else:
71- self.pager = console.config["pager"]
72+ self.pager_command = console.config["pager_command"]
73 self.last_desc = None
74 self.buffer = []
75
76@@ -129,6 +126,25 @@
77 self.prompt1 = prompt1
78 self.prompt2 = prompt2
79
80+ def print_with_pager(self, text):
81+ try:
82+ pager = subprocess.Popen(self.pager_command.split(),
83+ shell=False,
84+ stdin=subprocess.PIPE)
85+ except:
86+ sys.stdout.write("Unable to run pager command \"{0}\". Pager disabled.\n"
87+ .format(self.pager_command))
88+ self.pager_command = None
89+ return False
90+
91+ try:
92+ pager.communicate(text)
93+ except IOError:
94+ # IOError is raised sometimes with large outputs
95+ pass
96+
97+ return True
98+
99 def present(self, result):
100 """Print the result provided as an argument.
101
102@@ -167,17 +183,16 @@
103 self.last_desc = result["info"]
104 if result["result"]:
105 self.buffer.extend(result["result"])
106- elif self.buffer and self.pager is None:
107- for row in _gen_table():
108- sys.stdout.write(row)
109- # Reset values for next result set.
110- self.buffer = []
111- elif self.buffer and self.pager is not None and self.console.driver.is_interactive:
112- pager = subprocess.Popen(self.pager.split(), shell=False, stdin=subprocess.PIPE)
113- try:
114- pager.communicate("".join(_gen_table()))
115- except IOError:
116- pass
117+ elif self.buffer:
118+ printed = False
119+ if self.pager_command and self.console.driver.is_interactive:
120+ printed = self.print_with_pager("".join(_gen_table()))
121+
122+ # Fallback if no pager set, or paging fails.
123+ if not printed:
124+ for row in _gen_table():
125+ sys.stdout.write(row)
126+
127 # Reset values for next result set.
128 self.buffer = []
129 elif isinstance(result, Exception):

Subscribers

People subscribed via source and target branches

to all changes: