mercurial/dicthelpers.py
author Alexander Plavin <me@aplavin.ru>
Thu, 04 Jul 2013 14:18:44 +0400
changeset 19387 f2e4fdb3dd27
parent 18894 ed46c2b98b0d
permissions -rw-r--r--
hgweb: code selection without line numbers in file source view All the source lines are put in a <pre> tag, which gives correct display and copy&paste in both Chromium (WebKit) and FireFox: line numbers are not copied, all the tabs and spaces are kept. This doesn't change the visual appearance of the view compared to current hgweb version and doesn't use any JS code. Also, stripes in this view are now generated clientside with CSS. This implementation is chosen because other variants have important issues: Strategy FF Chrome current D,LT,E,T,L D,L pre S,NW S,NW pre/div/nbsp LT,E,T,TS,NW TS,NW pre/div/br LT,E,T,NW NW ol/li/nbsp LT,E,T,TS,AJ TS,AJ ol/li/br LT,E,T,AJ AJ pre/span LV LV Legend Strategies: - current: implemented in hgweb before this patch, i.e. divs for each line, and line numbers links in the div too - pre: the whole code in one pre tag with newlines, all line numbers in another one with 'float: left' - pre/div/{nbsp,br}: same as just 'pre', but separate divs for each line and &nbsp; or <br> instead of empty lines (otherwise they are not copied at all) - ol/li/{nbsp,br}: a single ol with li's and divs for each line, &nbsp; or <br> same as in previous strategy - pre/span: this patch Problems: D = (very minor) display problems, like wrong width of leading tabs LT = loses leading/trailing whitespace E = loses embedded whitespace B = loses blank lines T = loses tabs L = selects line numbers LV = (only) visually selects line numbers LVE = (only) visually selects line numbers at empty lines S = no stripes (and no ability to easily highlight lines-which-are-linked-at in the future) TS = space copied instead of empty line AJ = get anchor links only with JS (they work even without) NW = no linewrap easily possible (in future) As for browser versions compatibility, the CSS tricks used are supported in (according to caniuse.com): a) line numbers generation with 'content:' property and CSS counters: IE 8+, all other popular browsers (in pre-WebKit Opera numbers are being copied) b) stripes ('nth-child' selector): IE 8+, FF 3.5+, Safari 3.2+, Opera 9.5+, all other popular browsers c) line numbers are not visually selected ('user-select:' property): IE 10+, Opera 15.0+, all other popular browsers This patch is based on a demo implementation by Martin Geisler <martin@geisler.net>.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
18820
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     1
# dicthelpers.py - helper routines for Python dicts
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     2
#
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     3
# Copyright 2013 Facebook
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     4
#
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
     7
18847
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
     8
def diff(d1, d2, default=None):
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
     9
    '''Return all key-value pairs that are different between d1 and d2.
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    10
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    11
    This includes keys that are present in one dict but not the other, and
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    12
    keys whose values are different. The return value is a dict with values
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    13
    being pairs of values from d1 and d2 respectively, and missing values
18894
ed46c2b98b0d dicthelpers.diff: compare against default for missing values
Siddharth Agarwal <sid0@fb.com>
parents: 18847
diff changeset
    14
    treated as default, so if a value is missing from one dict and the same as
ed46c2b98b0d dicthelpers.diff: compare against default for missing values
Siddharth Agarwal <sid0@fb.com>
parents: 18847
diff changeset
    15
    default in the other, it will not be returned.'''
18820
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    16
    res = {}
18847
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    17
    if d1 is d2:
18820
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    18
        # same dict, so diff is empty
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    19
        return res
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    20
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    21
    for k1, v1 in d1.iteritems():
18894
ed46c2b98b0d dicthelpers.diff: compare against default for missing values
Siddharth Agarwal <sid0@fb.com>
parents: 18847
diff changeset
    22
        v2 = d2.get(k1, default)
ed46c2b98b0d dicthelpers.diff: compare against default for missing values
Siddharth Agarwal <sid0@fb.com>
parents: 18847
diff changeset
    23
        if v1 != v2:
ed46c2b98b0d dicthelpers.diff: compare against default for missing values
Siddharth Agarwal <sid0@fb.com>
parents: 18847
diff changeset
    24
            res[k1] = (v1, v2)
18820
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    25
18847
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    26
    for k2 in d2:
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    27
        if k2 not in d1:
18894
ed46c2b98b0d dicthelpers.diff: compare against default for missing values
Siddharth Agarwal <sid0@fb.com>
parents: 18847
diff changeset
    28
            v2 = d2[k2]
ed46c2b98b0d dicthelpers.diff: compare against default for missing values
Siddharth Agarwal <sid0@fb.com>
parents: 18847
diff changeset
    29
            if v2 != default:
ed46c2b98b0d dicthelpers.diff: compare against default for missing values
Siddharth Agarwal <sid0@fb.com>
parents: 18847
diff changeset
    30
                res[k2] = (default, v2)
18847
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    31
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    32
    return res
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    33
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    34
def join(d1, d2, default=None):
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    35
    '''Return all key-value pairs from both d1 and d2.
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    36
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    37
    This is akin to an outer join in relational algebra. The return value is a
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    38
    dict with values being pairs of values from d1 and d2 respectively, and
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    39
    missing values represented as default.'''
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    40
    res = {}
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    41
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    42
    for k1, v1 in d1.iteritems():
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    43
        if k1 in d2:
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    44
            res[k1] = (v1, d2[k1])
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    45
        else:
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    46
            res[k1] = (v1, default)
40c679748fa9 dicthelpers: inline diff and join code
Siddharth Agarwal <sid0@fb.com>
parents: 18846
diff changeset
    47
18820
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    48
    if d1 is d2:
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    49
        return res
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    50
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    51
    for k2 in d2:
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    52
        if k2 not in d1:
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    53
            res[k2] = (default, d2[k2])
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    54
a45e44d76c81 mercurial: implement diff and join for dicts
Siddharth Agarwal <sid0@fb.com>
parents:
diff changeset
    55
    return res