def listcmd (self, subcmds=None, wcol=None, stream=sys.stdout): """ Formatted listing of subcommands with short descriptions. @param subcmds: subcommand names (all subcommands if C{None}) @type subcmds: list of strings @param wcol: column to wrap text at (<= 0 for no wrapping, C{None} for automatic according to output stream) @type wcol: int @param stream: intended output stream for the text @type stream: file @return: formatted listing @rtype: string """ if subcmds is None: subcmds = self._scviews.keys() subcmds.sort() maxsclen = max([len(x) for x in subcmds]) ndsep = _("@item:intext splitter between a subcommand name " "and its description", " - ") flead = " " * 2 lead = flead + " " * (maxsclen + 3) if wcol is None: wcol = (term_width(stream=stream) or 80) - 1 fmts = [] for subcmd in subcmds: scview = self._scviews.get(subcmd, None) if scview is None: raise SubcmdError( _("@info", "Trying to include an unknown subcommand '%(cmd)s' " "into listing.", cmd=subcmd)) desc = scview.shdesc() if desc: name = cinterp("%%-%ds" % maxsclen, subcmd) s = name + ndsep + desc else: s = name lines = wrap_text(s, wcol=wcol, flead=flead, lead=lead, endl="") fmts.extend(lines) return cjoin(fmts, "\n")
def fmt_par (param, indent=""): s = "" s += indent + " " + param ptype = self._ptypes[param] if ptype is bool: s += " "*1 +_("@item:intext indicator that the parameter " "is a flag", "[flag]") else: metavar = self._metavars[param] if metavar is None: metavar = _("@item:intext default placehodler for " "the parameter argument", "ARG") s += cinterp(":%s", metavar) defval = self._defvals[param] admvals = self._admvals[param] if ptype is not bool and defval is not None and str(defval): cpos = len(s) - s.rfind("\n") - 1 s += " "*1 + _("@item:intext default value for the argument", "[default %(arg)s=%(val)s]", arg=metavar, val=defval) if admvals is not None: s += "\n" + (" " * cpos) if ptype is not bool and admvals is not None: s += " "*1 + _("@item:intext admissible argument values", "[%(arg)s is one of: %(vallist)s]", arg=metavar, vallist=format_item_list(admvals)) s += "\n" desc = self._descs[param] if desc: fmt_desc = fmt_wrap(desc, indent + " ") s += fmt_desc ## Wrap current parameter with empty lines if ## the description spanned several lines. #if "\n\n" in fmt_desc: #s = "\n" + s + "\n" s += "\n" # empty line after description return s
def warning_on_msg(text, msg, cat, subsrc=None, file=sys.stderr): """ Warning on a PO message. Outputs the message reference (catalog name and the message position), along with the warning text. @param text: text to report @type text: string @param msg: the message for which the text is reported @type msg: L{Message_base} @param cat: the catalog where the message lives @type cat: L{Catalog} @param subsrc: more detailed source of the message @type subsrc: C{None} or string @param file: send output to this file descriptor @type file: C{file} """ posinfo = _msg_pos_fmt(cat.filename, msg.refline, msg.refentry) text = cinterp("%s: %s", posinfo, text) warning(text, subsrc=subsrc, showcmd=False)
def error_on_msg(text, msg, cat, code=1, subsrc=None, file=sys.stderr): """ Error on a PO message (aborts the execution). Outputs the message reference (catalog name and message position), along with the error text. Aborts execution with the given code. @param text: text to report @type text: string @param msg: the message for which the text is reported @type msg: L{Message_base} @param cat: the catalog where the message lives @type cat: L{Catalog} @param code: the exit code @type code: int @param subsrc: more detailed source of the message @type subsrc: C{None} or string @param file: send output to this file descriptor @type file: C{file} """ posinfo = _msg_pos_fmt(cat.filename, msg.refline, msg.refentry) text = cinterp("%s: %s", posinfo, text) error(text, code=code, subsrc=subsrc, showcmd=True)
def report_on_msg_hl(highlight, msg, cat, fmsg=None, subsrc=None, file=sys.stdout): """ Report on parts of a PO message. For each of the spans found in the L{highlight<report_msg_content>} specification which have a note attached, outputs the position reference (catalog name, message position, spanned segment) and the span note. The highlight can be relative to a somewhat modified, filtered message instead of the original one. @param highlight: highlight specification @type highlight: L{highlight<report_msg_content>} @param msg: the message for which the text is reported @type msg: L{Message_base} @param cat: the catalog where the message lives @type cat: L{Catalog} @param fmsg: filtered message to which the highlight corresponds @type fmsg: L{Message_base} @param subsrc: more detailed source of the message @type subsrc: C{None} or string @param file: send output to this file descriptor @type file: C{file} """ refpos = _msg_pos_fmt(cat.filename, msg.refline, msg.refentry) if not fmsg: # use original message as filtered if not given fmsg = msg for hspec in highlight: name, item, spans = hspec[:3] if name == "msgctxt": text = msg.msgctxt or u"" ftext = fmsg.msgctxt or u"" elif name == "msgid": text = msg.msgid ftext = fmsg.msgid elif name == "msgid_plural": text = msg.msgid_plural or u"" ftext = fmsg.msgid_plural or u"" elif name == "msgstr": text = msg.msgstr[item] ftext = fmsg.msgstr[item] # TODO: Add more fields. else: warning( _("@info", "Unknown field '%(field)s' " "in highlighting specification.", field=name)) continue if len(hspec) > 3: # Override filtered text from filtered message # by filtered text from the highlight spec. ftext = hspec[3] spans = adapt_spans(text, ftext, spans, merge=False) if msg.msgid_plural is not None and name == "msgstr": name = "%s_%d" % (name, item) for span in spans: if len(span) < 3: continue start, end, snote = span if isinstance(start, int) and isinstance(end, int): seglen = end - start if seglen > 0: segtext = text[start:end] if len(segtext) > 30: segtext = segtext[:27] + "..." posinfo = "%s:%d:\"%s\"" % (name, start, escape(segtext)) else: posinfo = "%s:%d" % (name, start) else: posinfo = "%s" % name posinfo = ColorString("<green>%s</green>") % posinfo rtext = cinterp("%s[%s]: %s", refpos, posinfo, snote) report(rtext, subsrc=subsrc, showcmd=False)
def _bar_stats(self, counts, title, count, summed, dlabel, dcolumn): # Count categories to display and chars/colors associated to them. # Note: Use only characters from Latin1. tspecs = (("trn", u"×", "green"), ("fuz", u"¤", "blue"), ("unt", u"·", "red")) # Find out maximum counts overall. maxcounts = dict(trn=0, fuz=0, unt=0, tot=0) maxcounts_jumbled = maxcounts.copy() for otitle, ocount, osummed in counts: # If absolute bars, compare counts only for non-summed counts. if self.p.absolute and osummed: continue # Count both messages and words, for the number display padding. for tkey in maxcounts_jumbled: for dcol in (0, 1): c = ocount[tkey][dcol] if maxcounts_jumbled[tkey] < c: maxcounts_jumbled[tkey] = c for tkey in maxcounts: c = ocount[tkey][dcolumn] if maxcounts[tkey] < c: maxcounts[tkey] = c # Character widths of maximum count categories. maxcountscw = {} for tkey, tval in maxcounts.iteritems(): maxcountscw[tkey] = len(str(tval)) maxcountscw_jumbled = {} for tkey, tval in maxcounts_jumbled.iteritems(): maxcountscw_jumbled[tkey] = len(str(tval)) # Formatted counts by disjunct categories. fmt_counts = [] for tkey, tchar, tcol in tspecs: cstr = str(count[tkey][dcolumn]) if cstr == "0": cstr = "-" cfmt = ("%%%ds" % maxcountscw_jumbled[tkey]) % cstr if tcol is not None: fmt_counts.append( (ColorString("<%s>%%s</%s>") % (tcol, tcol)) % cfmt) else: fmt_counts.append(cfmt) fmt_counts = cjoin(fmt_counts, "/") # Maximum and nominal bar widths in characters. # TODO: Make parameters. if self.inline: nombarcw = 20 maxbarcw = 50 else: nombarcw = 40 maxbarcw = 80 def roundnear(x): return int(round(x, 0)) def roundup(x): ix = int(x) if x - ix > 1e-16: ix += 1 return ix # Compute number of cells per category. n_cells = {} if self.p.absolute: # Absolute bar. n_per_cell = 0 for npc in (1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000): if npc * maxbarcw > maxcounts["tot"]: n_per_cell = npc break if not n_per_cell: warning( _("@info", "Count too large, cannot display bar graph.")) return for tkey, roundf in (("fuz", roundup), ("unt", roundup), ("tot", roundnear)): c = count[tkey][dcolumn] n_cells[tkey] = roundf(float(c) / n_per_cell) # Correct the situation when there are no cells. if n_cells["tot"] < 1: n_cells["tot"] = 1 # Correct the situation when the sum of cells fuzzy+untranslated # goes over the total; give priority to untranslated when reducing. while n_cells["fuz"] + n_cells["unt"] > n_cells["tot"]: if n_cells["fuz"] >= n_cells["unt"]: n_cells["fuz"] -= 1 else: n_cells["unt"] -= 1 n_cells["trn"] = n_cells["tot"] - n_cells["fuz"] - n_cells["unt"] else: # Relative bar. if count["tot"][dcolumn] > 0: n_per_cell = float(nombarcw) / count["tot"][dcolumn] else: n_per_cell = 0 for tkey in ("fuz", "unt"): c = count[tkey][dcolumn] n_cells[tkey] = roundup(c * n_per_cell) # When there are almost none translated, it may have happened that # the sum of cells fuzzy+untranslated is over nominal; reduce. while n_cells["fuz"] + n_cells["unt"] > nombarcw: if n_cells["fuz"] >= n_cells["unt"]: n_cells["fuz"] -= 1 else: n_cells["unt"] -= 1 n_cells["trn"] = nombarcw - n_cells["fuz"] - n_cells["unt"] # Create the bar. fmt_bar = [] for tkey, tchar, tcol in tspecs: bar = tchar * n_cells[tkey] if tcol is not None: bar = (ColorString("<%s>%%s</%s>") % (tcol, tcol)) % bar fmt_bar.append(bar) fmt_bar = cjoin(fmt_bar) # Assemble final output. if not self.p.absolute or not summed: if count["tot"][dcolumn] == 0: fmt_bar = "" report(cinterp("%s %s |%s|", fmt_counts, dlabel, fmt_bar)) else: report(cinterp("%s %s", fmt_counts, dlabel))