diff --git a/cccli/command/list.py b/cccli/command/list.py index cce62e2b3dfd71350611147721641b502123f407..ebb4454e5adb329141978c7de911f21247a97236 100644 --- a/cccli/command/list.py +++ b/cccli/command/list.py @@ -10,6 +10,7 @@ from sjrpc.core.exceptions import * from cccli.printer import Printer, color from cccli.command.command import TqlCommand import math +import os class Command_list(TqlCommand): '''List objects''' @@ -21,6 +22,8 @@ class Command_list(TqlCommand): help="column aligment display") self.add_option("-l", action="store_true", dest="align", help="line aligment display") + self.add_option("-m", action="store_true", dest="mikrotik", + help="mikrotik display") self.remove_option("--quiet") self.remove_option("--direct") @@ -35,6 +38,8 @@ class Command_list(TqlCommand): self.list_align(objs) elif self.options.table: self.list_table(objs) + elif self.options.mikrotik: + self.list_mikrotik(objs) else: self.print_objects(objs, index=self.options.index) @@ -94,3 +99,81 @@ class Command_list(TqlCommand): self.printer.out(self.tdc(t), nl="") self.printer.out(self.tdr(t, o.get(t, u"")).ljust(tags[t]) ,nl=" ") self.printer.out(color["reset"]) + + def list_mikrotik(self, objs): + '''Mikrotik style display''' + term_height, term_width = self.printer.get_term_size() + # check if the line width is not too small for this kind of listing, + # 10 seem to be a good minimum value: + if term_width < 10: + raise cmdError("term width is too small") + # calculate the size of the marge, the taken value is equal to the + # maximum id length, capped to the 1/3 of the terminal width: + list_id = [len(o['id']) for o in objs['objects'] if len(o['id']) < term_width / 3] + if list_id: + margin = max(list_id) + 4 + else: + margin = term_width / 3 + # compute index width (part of the margin if apply): + if self.options.index: + indexw = int(math.log10(len(objs["objects"]))) + 1 + margin += indexw + # build full tag order list: + tags = set((t for o in objs['objects'] for t in o.keys())) + order = [t for t in objs.get("order", []) if t in tags] + order.extend(sorted(tags - set(order))) + # dislay each object + for i, o in enumerate(objs["objects"]): + line_pos = 0 + line = "" + if self.options.index: + line = ("[%d]"%i).ljust(indexw + 3) + line_pos = len(line) + # write the id tag on the margin: + tag = order[0] + # +2 is the size of space and ":" + id_size = line_pos + len(tag) + len(self.tdr(tag, o.get(tag))) + 2 + line += "%s%s:%s%s "%(self.tdtc(tag), tag, self.tdc(tag), self.tdr(tag, o.get(tag, u""))) + line_pos = margin + if id_size <= term_width / 3: + line += " " * (margin - id_size) + else: + line += os.linesep + " " * margin + # write all other tags after id: + for tag in order[1:]: + if o.get(tag) is not None: + # the +2 is the size of space and ":" + tag_size = len(tag) + len(self.tdr(tag, o.get(tag))) + 2 + # if tag doesn't fit into the space left on current line, + # we jump on a new line: + if line_pos + tag_size > term_width and margin != line_pos: + line_pos = margin + line += os.linesep + " " * margin + # write tag name: + buf, line_pos = self._format_indent_text(tag + ":", line_pos, margin, term_width) + line += self.tdtc(tag) + buf + # write tag value: + buf, line_pos = self._format_indent_text(self.tdr(tag, o.get(tag)) + " ", line_pos, margin, term_width) + line += self.tdc(tag) + buf + self.printer.out("%s%s%s"%(line, color["reset"], os.linesep)) + + def _format_indent_text(self, text, current_pos, min_pos, max_pos): + '''Reformat text to start in current_pos and fit in column between min_pos and max_pos + For example format_indent_text("tototatatiti", 3, 2, 6) return line = "tot\n otat\n atit\n i", current_pos = 3''' + buf = "" + last_size = 0 + while text: + # the loop insert newline and indent in text + tmp = text[:max_pos - current_pos] + text = text[max_pos - current_pos:] + last_size = current_pos + len(tmp) + buf += tmp + # if next text is not empty, newline and indent + if text != "": + buf += os.linesep + " " * min_pos + # if next text is just a space, stop loop + if text == " ": + last_size = min_pos + break + current_pos = min_pos + return buf, last_size