Staging
v0.5.1
https://foss.heptapod.net/mercurial/hgview
Revision f4249bb0342e14a98a70316637cf066371be1ec8 authored by Pierre-Yves David on 06 August 2012, 16:10:55 UTC, committed by Pierre-Yves David on 06 August 2012, 16:10:55 UTC
There is good reason for the filelog_graph not to be aware of stong and weak
relation. Moreover we will probably want to display obsolescence relation for
file too.

In the process the file log fill is properly set to "Strong" as it should have
always been.
1 parent 0c985b9
Raw File
Tip revision: f4249bb0342e14a98a70316637cf066371be1ec8 authored by Pierre-Yves David on 06 August 2012, 16:10:55 UTC
[lib+qt] Make the file log grapher returns 4 items lines directly
Tip revision: f4249bb
config.py
# -*- coding: utf-8 -*-
# Copyright (c) 2003-2011 LOGILAB S.A. (Paris, FRANCE).
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program.  If not, see <http://www.gnu.org/licenses/>.
#
# pylint: disable=C0103

"""
Module for managing configuration parameters of hgview using Hg's
configuration system
"""
from functools import partial
import os
import re
import shlex

def cached(meth):
    """
    decorator to cache config values once they are read
    """
    name = meth.func_name
    def wrapper(self, *args, **kw):
        if name in self._cache:
            return self._cache[name]
        res = meth(self, *args, **kw)
        self._cache[name] = res
        return res
    wrapper.__doc__ = meth.__doc__
    return wrapper

class HgConfig(object):
    """
    Class managing user configuration from hg standard configuration system (.hgrc)
    """
    def __init__(self, ui, section="hgview"):
        self.ui = ui
        self.section = section
        self._cache = {}

    def _fromconfig(self, name, default):
        '''allow per-interface configuration.
        look for ``interface.config`` then for ``config`` if the first were not
        found'''
        out = self.ui.config(self.section,
                             '.'.join((self.ui.opts.interface, name)),
                             None)
        if out is not None:
            return out
        return self.ui.config(self.section, name, default)

    @cached
    def getFancyReplace(self):
        r"""
        fancyreplace: ``"patt" "repl"`` used to modify description by replacing
            ``patt`` by ``repl`` using regular expression (``re.sub`` for instance).
            Ex: "#(\d+)":"`#\\1 <http://www.logilab.org/ticket/\\1>`_"
        """
        data = self._fromconfig('fancyreplace', None)
        if data is None:
            return data
        data = shlex.split(data)
        assert len(data) == 2
        patt, repl = data
        return partial(re.compile(patt).sub, repl)


    @cached
    def getFont(self, default='Monospace'):
        """
        font: default font used to display diffs and files. Use Qt4 format.
        """
        return self._fromconfig('font', default)

    @cached
    def getFontSize(self, default=9):
        """
        fontsize: text size in file content viewer
        """
        return int(self._fromconfig('fontsize', default))

    @cached
    def getDotRadius(self, default=8):
        """
        dotradius: radius (in pixels) of the dot in the revision graph
        """
        return int(self._fromconfig('dotradius', default))

    @cached
    def getUsers(self):
        """
        users: path of the file holding users configurations
        """
        users = {}
        aliases = {}
        usersfile = self._fromconfig('users', os.path.join('~', ".hgusers"))
        cfgfile = None
        if usersfile:
            try:
                cfgfile = open(os.path.expanduser(usersfile))
            except IOError:
                cfgfile = None

        if cfgfile:
            currid = None
            for line in cfgfile:
                line = line.strip()
                if not line or line.startswith('#'):
                    continue
                cmd, val = line.split('=', 1)
                if cmd == 'id':
                    currid = val
                    if currid in users:
                        print "W: user %s is defined several times" % currid
                    users[currid] = {'aliases': set()}
                elif cmd == "alias":
                    users[currid]['aliases'].add(val)
                    if val in aliases:
                        print ("W: alias %s is used in several "
                               "user definitions" % val)
                    aliases[val] = currid
                else:
                    users[currid][cmd] = val
        return users, aliases

    @cached
    def getFileDescriptionView(self, default='persistent'):
        """
        descriptionview:

          :asfile: compact view with changeset description in the file list
          :persistent: persistent view with changeset description always visible (default)
        """
        return self._fromconfig('descriptionview', default).lower()

    @cached
    def getFileDescriptionColor(self, default='magenta'):
        """
        filedescriptioncolor: display color of the "description" entry
        """
        return self._fromconfig('filedescriptioncolor', default)
    @cached
    def getFileModifiedColor(self, default='blue'):
        """
        filemodifiedcolor: display color of a modified file
        """
        return self._fromconfig('filemodifiedcolor', default)
    @cached
    def getFileRemovedColor(self, default='red'):
        """
        fileremovedcolor: display color of a removed file
        """
        return self._fromconfig('fileremovededcolor', default)
    @cached
    def getFileDeletedColor(self, default='darkred'):
        """
        filedeletedcolor: display color of a deleted file
        """
        return self._fromconfig('filedeletedcolor', default)
    @cached
    def getFileAddedColor(self, default='green'):
        """
        fileaddedcolor: display color of an added file
        """
        return self._fromconfig('fileaddedcolor', default)

    @cached
    def getRowHeight(self, default=20):
        """
        rowheight: height (in pixels) on a row of the revision table
        """
        return int(self._fromconfig('rowheight', default))

    @cached
    def getHideFindDelay(self, default=10000):
        """
        hidefinddelay: delay (in ms) after which the find bar will disappear
        """
        return int(self._fromconfig('hidefindddelay', default))

    @cached
    def getFillingStep(self, default=300):
        """
        fillingstep: number of nodes 'loaded' at a time when updating repo graph log
        """
        return int(self._fromconfig('fillingstep', default))

    @cached
    def getChangelogColumns(self, default=None):
        """
        changelogcolumns: ordered list of displayed columns in changelog views;
                    defaults to ID, Branch, Log, Author, Date, Tags
        """
        cols = self._fromconfig('changelogcolumns', default)
        if cols is None:
            return None
        return [col.strip() for col in cols.split(',') if col.strip()]

    @cached
    def getFilelogColumns(self, default=None):
        """
        filelogcolumns: ordered list of displayed columns in filelog views;
                  defaults to ID, Log, Author, Date
        """
        cols = self._fromconfig('filelogcolumns', default)
        if cols is None:
            return None
        return [col.strip() for col in cols.split(',') if col.strip()]

    @cached
    def getDisplayDiffStats(self, default="yes"):
        """
        displaydiffstats: flag controllong the appearance of the
                    'Diff' column in a revision's file list
        """
        val = str(self._fromconfig('displaydiffstats', default))
        return val.lower() in ['true', 'yes', '1', 'on']

    @cached
    def getMaxFileSize(self, default=100000):
        """
        maxfilesize: max size of a file for diff computations, display content, etc.
                     (-1 means no max size)
        """
        return int(self._fromconfig('maxfilesize', default))

    @cached
    def getDiffBGColor(self, default='black'):
        """
        diffbgcolor: background color of diffs
        """
        return self._fromconfig('diffbgcolor', default)

    @cached
    def getDiffFGColor(self, default='white'):
        """
        difffgcolor: text color of diffs
        """
        return self._fromconfig('difffgcolor', default)

    @cached
    def getDiffPlusColor(self, default='green'):
        """
        diffpluscolor: text color of added lines in diffs
        """
        return self._fromconfig('diffpluscolor', default)

    @cached
    def getDiffMinusColor(self, default='red'):
        """
        diffminuscolor: text color of removed lines in diffs
        """
        return self._fromconfig('diffminuscolor', default)

    @cached
    def getDiffSectionColor(self, default='magenta'):
        """
        diffsectioncolor: text color of new section in diffs
        """
        return self._fromconfig('diffsectioncolor', default)

    @cached
    def getMQFGColor(self, default='#ff8183'):
        """
        mqfgcolor: bg color to highlight mq patches
        """
        return self._fromconfig('mqfgcolor', default)

    @cached
    def getMQHideTags(self, default=False):
        """
        mqhidetags: hide mq tags
        """
        return self._fromconfig('mqhidetags', default)

    @cached
    def getToolBarRevAtStartup(self, default=True):
        """
        toolbarrev: show hidden changeset at startup
        """
        return bool(self._fromconfig('toolbarrev', default))

    @cached
    def getToolBarDiffAtStartup(self, default=True):
        """
        toolbardiff: show hidden changeset at startup
        """
        return bool(self._fromconfig('toolbardiff', default))

    @cached
    def getContentAtStartUp(self, default=True):
        """
        contentatstartup: show the content of changeset at startup (bottom part)
        """
        return bool(self._fromconfig('contentatstartup', default))

    @cached
    def getShowHidden(self, default=False):
        """
        showhidden: show hidden changeset at startup
        """
        return bool(self._fromconfig('showhidden', default))

    @cached
    def getInterface(self, default=None):
        """
        interface: which GUI interface to use (among "qt", "raw" and "curses")
        """
        return self.ui.config(self.section, 'interface', default)

    @cached
    def getNonPublicOnTop(self, default=False):
        """
        nonpublicontop: display non public changesets on top of the graph log
                        (disabled with *show hidden*)
        """
        return bool(self._fromconfig('nonpublicontop', default))

    @cached
    def getShowObsolete(self, default=True):
        """
        showobsolete: display obsolete relations
        """
        return bool(self._fromconfig('showobsolete', default))

_HgConfig = HgConfig
# HgConfig is instanciated only once (singleton)
#
# this 'factory' is used to manage this (not using heavy guns of
# metaclass or so)
_hgconfig = None
def HgConfig(ui):
    """Factory to instanciate HgConfig class as a singleton
    """
    # pylint: disable=E0102
    global _hgconfig
    if _hgconfig is None:
        _hgconfig = _HgConfig(ui)
    return _hgconfig


def get_option_descriptions(rest=False):
    """
    Extract options descriptions (docstrings of HgConfig methods)
    """
    options = []
    for attr in dir(_HgConfig):
        if attr.startswith('get'):
            meth = getattr(_HgConfig, attr)
            if callable(meth):
                doc = meth.__doc__
                if doc and doc.strip():
                    doc = doc.strip()
                    if rest:
                        doc = re.sub(r' *(?P<arg>.*) *: *(?P<desc>.*)', r'``\1`` \2', doc.strip())
                        doc = ' '.join(doc.split()) # remove \n and other multiple whitespaces
                    options.append(doc)
    return options

back to top