← Back to team overview

launchpad-reviewers team mailing list archive

Re: [Merge] lp:~blr/launchpad/bug-1430597-kb-shortcuts-diff-view into lp:launchpad

 

Review: Approve code

Just a couple of trivial fixes.

Diff comments:

> === modified file 'lib/canonical/launchpad/icing/style.css'
> --- lib/canonical/launchpad/icing/style.css	2014-11-27 19:57:29 +0000
> +++ lib/canonical/launchpad/icing/style.css	2015-04-09 03:38:19 +0000
> @@ -597,6 +597,14 @@
>     background-color: white;
>     margin-bottom: 0.5em;
>  }
> +
> +table.diff .nav-cursor:before {
> +   content: "\0025B6";
> +   font-weight: bold;
> +   display: block;
> +   float: left;
> +   margin-left: 1.25em;
> +}
>  table.diff .text { padding-left: 0.5em; }
>  table.diff .line-no {
>    text-align: right;
> @@ -604,7 +612,9 @@
>    color: #999;
>    border-right: solid 4px white;
>    width: 4em;
> +  cursor: pointer;
>  }
> +
>  table.diff .line-no.active {
>    background: url(/@@/add) #f6f6f6 center left no-repeat;
>  }
> 
> === modified file 'lib/lp/code/javascript/branchmergeproposal.inlinecomments.js'
> --- lib/lp/code/javascript/branchmergeproposal.inlinecomments.js	2014-11-30 22:03:05 +0000
> +++ lib/lp/code/javascript/branchmergeproposal.inlinecomments.js	2015-04-09 03:38:19 +0000
> @@ -9,6 +9,16 @@
>  
>  YUI.add('lp.code.branchmergeproposal.inlinecomments', function(Y) {
>  
> +if (typeof window.KeyEvent === "undefined") {
> +    window.KeyEvent = {
> +        DOM_VK_RETURN: 13,
> +        DOM_VK_J: 74,
> +        DOM_VK_K: 75,
> +        DOM_VK_N: 78,
> +        DOM_VK_P: 80
> +    };
> +}
> +
>  // Grab the namespace in order to be able to expose the connect methods.
>  var namespace = Y.namespace('lp.code.branchmergeproposal.inlinecomments');
>  
> @@ -88,9 +98,8 @@
>              draft_div.one('.editorShortcutTip').remove();
>          });
>          widget.editor.on('keydown', function(e) {
> -           var enterKeyCode = 13;
>             if (e.domEvent.ctrlKey === true &&
> -               e.domEvent.button === enterKeyCode) {
> +               e.domEvent.button === window.KeyEvent.DOM_VK_RETURN) {
>                 this.save();
>             }
>          });
> @@ -118,7 +127,6 @@
>          namespace.delete_draft(draft_div);
>          namespace.flush_drafts_to_server();
>      };
> -
>      // The editor can be invoked by double-clicking a diff line or
>      // clicking the line number. Hovering over a line shows an edit icon
>      // near the line number, to hint that it's clickable.
> @@ -238,6 +246,8 @@
>                      namespace.create_row(comment);
>                  });
>                  Y.fire('inlinecomment.UPDATED');
> +                // Initialise key event navigation
> +                namespace.init_keynav();
>              }
>          },
>          parameters: {
> @@ -706,6 +716,113 @@
>  
>  });
>  
> +namespace.init_keynav = function() {
> +    var diff_nav_keys = [window.KeyEvent.DOM_VK_J,
> +                         window.KeyEvent.DOM_VK_K,
> +                         window.KeyEvent.DOM_VK_N,
> +                         window.KeyEvent.DOM_VK_P];
> +
> +    namespace.headers = namespace.get_headers();
> +    namespace.scrollPos = -1;
> +
> +    if (!namespace.handle_nav_keys_attached) {
> +        Y.one('body').on('key', namespace.handle_nav_keys,
> +                         'down:' + diff_nav_keys.join(','));
> +    }
> +    namespace.handle_nav_keys_attached = true;
> +};
> +
> +namespace.get_headers = function() {
> +    return document.querySelectorAll(
> +        'table.diff td.diff-file, table.diff td.diff-chunk');
> +};
> +
> +namespace.add_nav_cursor = function(headers, row) {
> +    var prev_header = headers[namespace.scrollPos];
> +    var nav_cursor_class = 'nav-cursor';
> +    if (prev_header) {
> +        Y.one(prev_header).previous().removeClass(nav_cursor_class);
> +    }
> +    Y.one(row.children[0]).addClass(nav_cursor_class);

nav_cursor_class is a fairly pointless variable, and might it make sense to just remove any headers that have the class rather than relying on scrollPos not being set to the new value yet?

> +};
> +
> +namespace.get_header_row = function(headers, pos) {
> +    // XXX blr 20150407: Workaround for rare case where the headers collection
> +    // inexplicably loses parentNodes.
> +    if (!headers[pos].parentNode) {
> +        namespace.headers = namespace.get_headers();
> +        headers = namespace.headers;
> +    }
> +    return {'row': headers[pos].parentNode, 'pos': pos};
> +};
> +
> +namespace.header_has_type = function(header, type) {
> +    return header.className.indexOf(type) > -1;
> +};
> +
> +namespace.get_next_header = function(headers, type, direction) {
> +    var cursor = namespace.scrollPos;
> +    var i;
> +    if (headers.length <= 1) {
> +        return namespace.get_header_row(headers, 0);
> +    }
> +    if (direction === 'forwards') {
> +        for (i=cursor + 1; i < headers.length; i++) {
> +            if (namespace.header_has_type(headers[i], type)) {
> +                return namespace.get_header_row(headers, i);
> +            }
> +        }
> +    } else {
> +        if (cursor >= -1 && cursor <= 1) { cursor = headers.length; }
> +        for (i=cursor - 1; i > -1; --i) {
> +            if (namespace.header_has_type(headers[i], type)) {
> +                return namespace.get_header_row(headers, i);
> +            }
> +        }
> +    }
> +    // fallthrough case sets state to first header or chunk.
> +    if (type === 'file') {
> +        return namespace.get_header_row(headers, 0);
> +

Pointless blank?

> +    } else {
> +        return namespace.get_header_row(headers, 1);
> +    }
> +};
> +
> +namespace.scroll_to_header = function(type, direction) {
> +    if (namespace.headers.length > 0) {
> +        var header = namespace.get_next_header(
> +            namespace.headers, type, direction);
> +        namespace.add_nav_cursor(namespace.headers, header.row);
> +        namespace.scrollPos = header.pos;
> +        header.row.scrollIntoView({block: 'start', behavior: 'smooth'});
> +    }
> +};
> +
> +/*
> + * Vim style bindings for diff previews. n/p (hunks), j/k (files)
> + */
> +namespace.handle_nav_keys = function(e) {
> +    // Do not respond to keydown events for modkeys or when elements
> +    // have focus.
> +    if (e.altKey || e.ctrlKey || e.shiftKey ||
> +        document.querySelector(":focus")) {
> +        return;
> +    }
> +    if (e.button === window.KeyEvent.DOM_VK_J) {
> +        namespace.scroll_to_header('file', 'forwards');
> +    }
> +    if (e.button === window.KeyEvent.DOM_VK_K) {
> +        namespace.scroll_to_header('file', 'backwards');
> +    }
> +    if (e.button === window.KeyEvent.DOM_VK_N) {
> +        namespace.scroll_to_header('chunk', 'forwards');
> +    }
> +    if (e.button === window.KeyEvent.DOM_VK_P) {
> +        namespace.scroll_to_header('chunk', 'backwards');
> +    }
> +};
> +
>  namespace.DiffNav = DiffNav;
>  
>  }, '0.1', {requires: ['datatype-date', 'event', 'io', 'node', 'widget',
> 
> === modified file 'lib/lp/code/javascript/tests/test_branchmergeproposal.inlinecomments.html'
> --- lib/lp/code/javascript/tests/test_branchmergeproposal.inlinecomments.html	2014-07-03 21:13:16 +0000
> +++ lib/lp/code/javascript/tests/test_branchmergeproposal.inlinecomments.html	2015-04-09 03:38:19 +0000
> @@ -119,16 +119,52 @@
>              <tbody>
>                  <tr id="diff-line-1">
>                      <td class="line-no">1</td>
> -                    <td class="diff-header text">foo bar</td>
> -                </tr>
> -                <tr id="diff-line-2">
> -                    <td class="line-no">2</td>
> -                    <td class="text">baz</td>
> -                </tr>
> -                <tr id="diff-line-3">
> -                    <td class="line-no">3</td>
> -                    <td class="text">quux</td>
> -                </tr>
> +                    <td class="diff-file text">
> +                        === zbqvsvrq svyr 'yvo/yc/nafjref/grfgf/grfg_dhrfgvba_jrofreivpr.cl'
> +                    </td>
> +                </tr>
> +                    <tr id="diff-line-2">
> +                        <td class="line-no">2</td>
> +                        <td class="diff-header text">
> +                            --- yvo/yc/nafjref/grfgf/grfg_dhrfgvba_jrofreivpr.cl 2015-03-13 04:07:31 +0000
> +                        </td>
> +                    </tr>
> +                    <tr id="diff-line-3">
> +                        <td class="line-no">3</td>
> +                        <td class="diff-header text">
> +                            +++ yvo/yc/nafjref/grfgf/grfg_dhrfgvba_jrofreivpr.cl 2015-03-17 15:34:05 +0000
> +                        </td>
> +                    </tr>
> +                    <tr id="diff-line-4">
> +                        <td class="line-no">4</td>
> +                        <td class="diff-chunk text">
> +                            @@ -1,12 +1,18 @@
> +                        </td>
> +                    </tr>
> +                    <tr id="diff-line-5">
> +                        <td class="line-no">5</td>
> +                        <td class="diff-text">
> +                            -# Pbclevtug 2011 Pnabavpny Ygq.  Guvf fbsgjner vf yvprafrq haqre gur
> +                        </td>
> +                    </tr>
> +                    <tr id="diff-line-6">
> +                        <td class="line-no">6</td>
> +                        <td class="diff-chunk text">
> +                            @@ -30,6 +36,7 @@
> +                        </td>
> +                    </tr>
> +                    <tr id="diff-line-7">
> +                        <td class="line-no">7</td>
> +                        <td class="text">
> +                            erpbeq_gjb_ehaf,
> +                        </td>
> +                    </tr>
> +                    <tr id="diff-line-8">
> +                        <td class="line-no">8</td>
> +                        <td class="diff-file text">
> +                            === zbqvsvrq svyr 'yvo/yc/pbqr/oebjfre/pbasvther.mpzy'
> +                        </td>
> +                    </tr>
>              </tbody>
>          </table>
>  
> 
> === modified file 'lib/lp/code/javascript/tests/test_branchmergeproposal.inlinecomments.js'
> --- lib/lp/code/javascript/tests/test_branchmergeproposal.inlinecomments.js	2014-11-27 22:27:28 +0000
> +++ lib/lp/code/javascript/tests/test_branchmergeproposal.inlinecomments.js	2015-04-09 03:38:19 +0000
> @@ -47,7 +47,6 @@
>              module.current_previewdiff_id = 1;
>              module.populate_comments();
>              module.populate_drafts();
> -
>              // LP was hit twice for fetching published and draft inline
>              // comments
>              Y.Assert.areEqual(2, mockio.requests.length);
> @@ -57,7 +56,7 @@
>              Y.Assert.areSame(
>                  "ws.op=getDraftInlineComments&previewdiff_id=1",
>                  mockio.requests[1].config.data);
> -            draft_comments = {'2': 'Boing!', '3': 'Zoing!'};
> +            var draft_comments = {'2': 'Boing!', '3': 'Zoing!'};
>              mockio.success({
>                  responseText: Y.JSON.stringify(draft_comments),
>                  responseHeaders: {'Content-Type': 'application/json'}});
> @@ -69,8 +68,8 @@
>                  "ws.op=getInlineComments&previewdiff_id=1",
>                  mockio.requests[0].config.data);
>              mockio.last_request = mockio.requests[0];
> -            var now = (new Date).valueOf();
> -            published_comments = [
> +            var now = (new Date()).valueOf();
> +            var published_comments = [
>                  {'line_number': '2',
>                   'person': person_obj,
>                   'text': 'This is preloaded.',
> @@ -78,7 +77,7 @@
>                  {'line_number': '3',
>                   'person': person_obj,
>                   'text': 'This is great.',
> -                 'date': (new Date(now - 12600000)),
> +                 'date': (new Date(now - 12600000))
>                  }
>              ];
>              mockio.success({
> @@ -97,7 +96,7 @@
>  
>              // Draft comment for line 2 is displayed after all published
>              // comments.
> -            var second = first.next()
> +            var second = first.next();
>              Y.Assert.areEqual(
>                  'Unsaved comment',
>                  second.one('.boardCommentDetails').get('text'));
> @@ -175,7 +174,7 @@
>              module.add_doubleclick_handler();
>              var line  = Y.one('#diff-line-1');
>              line.simulate('dblclick');
> -            ic_area = line.next();
> +            var ic_area = line.next();
>              ic_area.one('.yui3-ieditor-input>textarea').set('value', '');
>              ic_area.one('.lazr-neg').simulate('click');
>              Y.Assert.areEqual('diff-line-2', line.next().get('id'));
> @@ -188,7 +187,7 @@
>              var line = Y.one('#diff-line-1'),
>                  enterKeyCode = 13;
>              line.simulate('dblclick');
> -            ic_area = line.next();
> +            var ic_area = line.next();
>              ic_area.one('.yui3-ieditor-input>textarea')
>                .set('value', 'test comment');
>              ic_area.one('.lazr-pos').simulate('keypress',
> @@ -205,7 +204,7 @@
>  
>          test_logged_in: function() {
>              var called = false;
> -            add_doubleclick_handler = function() {
> +            var add_doubleclick_handler = function() {
>                  called = true;
>              };
>              module.add_doubleclick_handler = add_doubleclick_handler;
> @@ -236,6 +235,40 @@
>              Y.Assert.isFalse(doubleclick_called);
>              Y.Assert.isFalse(draft_called);
>              Y.Assert.areEqual(1, module.current_previewdiff_id);
> +        },
> +
> +        test_diff_keynav_file_header_nav: function() {
> +            module.init_keynav();
> +            var body = Y.one('body');
> +            var file_row_first = Y.one('#diff-line-1');
> +            var file_row_last = Y.one('#diff-line-8');
> +            var cursor;
> +
> +            body.simulate("keydown", { charCode: 75 });
> +            cursor = file_row_last.one('*');
> +            Y.Assert.areEqual('line-no nav-cursor',
> +                              cursor.get('className'));
> +            body.simulate("keydown", { charCode: 74 });
> +            cursor = file_row_first.one('*');
> +            Y.Assert.areEqual('line-no nav-cursor',
> +                              cursor.get('className'));
> +        },
> +
> +        test_diff_keynav_chunk_header_nav: function() {
> +            module.init_keynav();
> +            var body = Y.one('body');
> +            var chunk_row_first = Y.one('#diff-line-4');
> +            var chunk_row_last = Y.one('#diff-line-6');
> +            var cursor;
> +
> +            body.simulate("keydown", { charCode: 80 });
> +            cursor = chunk_row_last.one('*');
> +            Y.Assert.areEqual('line-no nav-cursor',
> +                              cursor.get('className'));
> +            body.simulate("keydown", { charCode: 78 });
> +            cursor = chunk_row_first.one('*');
> +            Y.Assert.areEqual('line-no nav-cursor',
> +                              cursor.get('className'));
>          }
>  
>      }));
> @@ -263,7 +296,7 @@
>                  self.inline_comments_requested_id = previewdiff_id;
>              };
>              // Create an instrument DiffNav instance.
> -            lp_client = new Y.lp.client.Launchpad(
> +            var lp_client = new Y.lp.client.Launchpad(
>                   {io_provider: new Y.lp.testing.mockio.MockIo()});
>              this.diffnav = new module.DiffNav(
>                   {srcNode: Y.one('#review-diff'), lp_client: lp_client}
> @@ -331,9 +364,11 @@
>              Y.Assert.areEqual(101, this.inline_comments_requested_id);
>              // Diff content is rendered/updated.
>              var comment = Y.one(
> -                '.diff-content table tbody tr td').next()
> +                '.diff-content table tbody tr td').next();
>              Y.Assert.areSame(
> -                 "foo bar", comment.get('text'));
> +                 "=== zbqvsvrq svyr 'yvo/yc/nafjref/grfgf/grfg_dhrfgvba_jrofreivpr.cl'",
> +                comment.get('text').trim());
> +
>              // The option corresponding to the current 'preview_diff'
>              // is selected and contains the expected text (title and
>              // formatted date_created).
> @@ -414,7 +449,7 @@
>              // PublishDraft() widget modifies the add-comment form
>              // (adding/removing 'publish_inlines' checkbox) according
>              // to the existence of draft inline comments.
> -            var container = Y.one('.publish_drafts_container')
> +            var container = Y.one('.publish_drafts_container');
>              Y.Assert.areEqual('', container.get('text'));
>              Y.Assert.isNull(container.one('[type=checkbox]'));
>              // A event is fired when the inlinecomments set changes.
> @@ -447,9 +482,11 @@
>              // The needed review-comment scrollers (Show diff comments)
>              // are created. Only 'current' (non-superseded) comments
>              // associated with inline comments get a scroller.
> -            var lines = []
> +            var lines = [];
>              Y.one('.conversation').get('text').split('\n').forEach(
> -                function(line) { if (line.trim()) lines.push(line.trim()); }
> +                function(line) {
> +                    if (line.trim()) { lines.push(line.trim()); }
> +                }
>              );
>              Y.ArrayAssert.itemsAreEqual(
>                  ['Comment from superseded',
> @@ -460,7 +497,7 @@
>              // Scroller are identified as:
>              // 'ic-scroller-<previewdiff_id>-<comment_id>'.
>              var comment = Y.one('[data-comment-id="2"]');
> -            var scroller = comment.one('.ic-scroller')
> +            var scroller = comment.one('.ic-scroller');
>              // We need to re-instrument the scroller in other to
>              // instantly fire the 'end' event (which runs the code
>              // that matters to us).
> @@ -539,7 +576,7 @@
>              // We need to re-instrument the scroller in other to
>              // instantly fire the 'end' event (which runs the code
>              // that matters to us).
> -            scroller = Y.one('.review-comment-scroller');
> +            var scroller = Y.one('.review-comment-scroller');
>              scroller.on('click', function() {
>                  var rc = Y.lp.code.branchmergeproposal.reviewcomment;
>                  rc.window_scroll_anim.fire('end');
> 
> === modified file 'lib/lp/code/stories/branches/xx-branchmergeproposals.txt'
> --- lib/lp/code/stories/branches/xx-branchmergeproposals.txt	2014-02-25 16:53:24 +0000
> +++ lib/lp/code/stories/branches/xx-branchmergeproposals.txt	2015-04-09 03:38:19 +0000
> @@ -622,7 +622,7 @@
>  The text of the review diff is in the page.
>  
>      >>> print repr(extract_text(get_review_diff()))
> -    u'Preview Diff\nDownload diff\n1\n...Fake Diff\u1010'
> +    u'Preview Diff\n[J/K] Next/Prev File, [N/P] Next/Prev Hunk\nDownload diff\n1\n---\n2\n+++\n3\n@@ -0,0 +1 @@\n4\n+Fake Diff\u1010'
>  
>  There is also a link to the diff URL, which is the preview diff URL plus
>  "+files/preview.diff". It redirects logged in users to the file in the
> 
> === modified file 'lib/lp/code/templates/branchmergeproposal-diff.pt'
> --- lib/lp/code/templates/branchmergeproposal-diff.pt	2014-05-15 12:53:25 +0000
> +++ lib/lp/code/templates/branchmergeproposal-diff.pt	2015-04-09 03:38:19 +0000
> @@ -6,6 +6,7 @@
>         tal:define="attachment view/preview_diff/diff_text">
>      <tal:real-diff condition="attachment">
>        <div class="boardCommentDetails filename">
> +        <div class="editorShortcutTip">[J/K] Next/Prev File, [N/P] Next/Prev Hunk</div>
>          <ul class="horizontal">
>            <li>
>              <a tal:attributes="href view/preview_diff/fmt:url">
> 
> === added directory 'lib/lp/testing/data'
> === added file 'lib/lp/testing/data/large.diff'
> --- lib/lp/testing/data/large.diff	1970-01-01 00:00:00 +0000
> +++ lib/lp/testing/data/large.diff	2015-04-09 03:38:19 +0000
> @@ -0,0 +1,191 @@
> +=== zbqvsvrq svyr 'yvo/yc/nafjref/grfgf/grfg_dhrfgvba_jrofreivpr.cl'
> +--- yvo/yc/nafjref/grfgf/grfg_dhrfgvba_jrofreivpr.cl    2015-03-13 04:07:31 +0000
> ++++ yvo/yc/nafjref/grfgf/grfg_dhrfgvba_jrofreivpr.cl    2015-03-17 15:34:05 +0000
> +@@ -1,12 +1,18 @@
> +-# Pbclevtug 2011 Pnabavpny Ygq.  Guvf fbsgjner vf yvprafrq haqre gur
> ++# Pbclevtug 2011-2015 Pnabavpny Ygq.  Guvf fbsgjner vf yvprafrq haqre gur
> + # TAH Nssreb Trareny Choyvp Yvprafr irefvba 3 (frr gur svyr YVPRAFR).
> + 
> + """Jrofreivpr havg grfgf eryngrq gb Ynhapucnq Dhrfgvbaf."""
> + 
> + __zrgnpynff__ = glcr
> + 
> ++sebz qngrgvzr vzcbeg (
> ++    qngrgvzr,
> ++    gvzrqrygn,
> ++    )
> ++
> + sebz OrnhgvshyFbhc vzcbeg OrnhgvshyFbhc
> + sebz ynme.erfgshypyvrag.reebef vzcbeg UGGCReebe
> ++vzcbeg clgm
> + sebz fvzcyrwfba vzcbeg qhzcf
> + sebz grfggbbyf.zngpuref vzcbeg Rdhnyf
> + vzcbeg genafnpgvba
> +@@ -30,6 +36,7 @@
> +     erpbeq_gjb_ehaf,
> +     GrfgPnfr,
> +     GrfgPnfrJvguSnpgbel,
> ++    gvzr_pbhagre,
> +     jf_bowrpg,
> +     )
> + sebz yc.grfgvat.ynlref vzcbeg (
> +@@ -257,7 +264,11 @@
> +     ynlre = QngnonfrShapgvbanyYnlre
> + 
> +     qrs grfg_frnepuDhrfgvbaf(frys):
> +-        perngrq = [frys.snpgbel.znxrDhrfgvba(gvgyr="sbb") sbe v va enatr(10)]
> ++        qngr_tra = gvzr_pbhagre(
> ++            qngrgvzr(2015, 01, 01, gmvasb=clgm.HGP), gvzrqrygn(qnlf=1))
> ++        perngrq = [
> ++            frys.snpgbel.znxrDhrfgvba(gvgyr="sbb", qngrperngrq=arkg(qngr_tra))
> ++            sbe v va enatr(10)]
> +         jrofreivpr = jrofreivpr_sbe_crefba(frys.snpgbel.znxrCrefba())
> +         pbyyrpgvba = jrofreivpr.anzrq_trg(
> +             '/dhrfgvbaf', 'frnepuDhrfgvbaf', frnepu_grkg='sbb',
> +=== zbqvsvrq svyr 'yvo/yc/pbqr/oebjfre/pbasvther.mpzy'
> +--- yvo/yc/pbqr/oebjfre/pbasvther.mpzy	2015-03-13 14:15:24 +0000
> ++++ yvo/yc/pbqr/oebjfre/pbasvther.mpzy	2015-03-19 17:04:22 +0000
> +@@ -806,12 +806,27 @@
> +         cngu_rkcerffvba="fgevat:+ers/${cngu}"
> +         nggevohgr_gb_cnerag="ercbfvgbel"
> +         ebbgfvgr="pbqr"/>
> +-    <oebjfre:cntr
> ++    <oebjfre:cntrf
> +         sbe="yc.pbqr.vagresnprf.tvgers.VTvgErs"
> +         pynff="yc.pbqr.oebjfre.tvgers.TvgErsIvrj"
> +-        crezvffvba="ynhapucnq.Ivrj"
> +-        anzr="+vaqrk"
> +-        grzcyngr="../grzcyngrf/tvgers-vaqrk.cg"/>
> ++        crezvffvba="ynhapucnq.Ivrj">
> ++        <oebjfre:cntr
> ++            anzr="+vaqrk"
> ++            grzcyngr="../grzcyngrf/tvgers-vaqrk.cg"/>
> ++        <oebjfre:cntr
> ++            anzr="++ers-pbzzvgf"
> ++            grzcyngr="../grzcyngrf/tvgers-pbzzvgf.cg"/>
> ++    </oebjfre:cntrf>
> ++    <oebjfre:cntr
> ++        sbe="yc.pbqr.vagresnprf.tvgers.VTvgErs"
> ++        anzr="+znpebf"
> ++        crezvffvba="mbcr.Choyvp"
> ++        grzcyngr="../grzcyngrf/tvgers-znpebf.cg"/>
> ++    <oebjfre:cntr
> ++        sbe="yc.pbqr.vagresnprf.tvgers.VTvgErsOngpuAnivtngbe"
> ++        crezvffvba="mbcr.Choyvp"
> ++        anzr="+ers-yvfgvat"
> ++        grzcyngr="../grzcyngrf/tvgers-yvfgvat.cg"/>
> + 
> +     <oebjfre:zrahf
> +         pynffrf="CebqhpgOenapurfZrah"
> +
> +=== zbqvsvrq svyr 'yvo/yc/pbqr/oebjfre/tvgers.cl'
> +--- yvo/yc/pbqr/oebjfre/tvgers.cl	2015-03-13 14:15:24 +0000
> ++++ yvo/yc/pbqr/oebjfre/tvgers.cl	2015-03-19 17:04:22 +0000
> +@@ -17,3 +17,12 @@
> +     @cebcregl
> +     qrs ynory(frys):
> +         erghea frys.pbagrkg.qvfcynl_anzr
> ++
> ++    @cebcregl
> ++    qrs gvc_pbzzvg_vasb(frys):
> ++        erghea {
> ++            "fun1": frys.pbagrkg.pbzzvg_fun1,
> ++            "nhgube": frys.pbagrkg.nhgube,
> ++            "nhgube_qngr": frys.pbagrkg.nhgube_qngr,
> ++            "pbzzvg_zrffntr": frys.pbagrkg.pbzzvg_zrffntr,
> ++            }
> +
> +=== zbqvsvrq svyr 'yvo/yc/pbqr/oebjfre/tvgercbfvgbel.cl'
> +--- yvo/yc/pbqr/oebjfre/tvgercbfvgbel.cl	2015-03-13 14:15:24 +0000
> ++++ yvo/yc/pbqr/oebjfre/tvgercbfvgbel.cl	2015-03-24 13:10:52 +0000
> +@@ -18,6 +18,7 @@
> + 
> + sebz yc.ncc.oebjfre.vasbezngvbaglcr vzcbeg VasbezngvbaGlcrCbegyrgZvkva
> + sebz yc.ncc.reebef vzcbeg AbgSbhaqReebe
> ++sebz yc.pbqr.vagresnprf.tvgers vzcbeg VTvgErsOngpuAnivtngbe
> + sebz yc.pbqr.vagresnprf.tvgercbfvgbel vzcbeg VTvgErcbfvgbel
> + sebz yc.freivprf.pbasvt vzcbeg pbasvt
> + sebz yc.freivprf.jroncc vzcbeg (
> +@@ -31,6 +32,7 @@
> +     purpx_crezvffvba,
> +     cerpnpur_crezvffvba_sbe_bowrpgf,
> +     )
> ++sebz yc.freivprf.jroncc.ongpuvat vzcbeg GnoyrOngpuAnivtngbe
> + sebz yc.freivprf.jroncc.oernqpehzo vzcbeg AnzrOernqpehzo
> + sebz yc.freivprf.jroncc.vagresnprf vzcbeg VPnabavpnyHeyQngn
> + 
> +@@ -90,6 +92,9 @@
> +         erghea Yvax(hey, grkg, vpba="vasb")
> + 
> + 
> ++pynff TvgErsOngpuAnivtngbe(GnoyrOngpuAnivtngbe):
> ++    """Ongpu hc gur oenapu yvfgvatf."""
> ++    vzcyrzragf(VTvgErsOngpuAnivtngbe)
> + pynff TvgErcbfvgbelIvrj(VasbezngvbaGlcrCbegyrgZvkva, YnhapucnqIvrj):
> + 
> +     @cebcregl
> +@@ -128,3 +152,7 @@
> +     qrs hfre_pna_chfu(frys):
> +         """Jurgure gur hfre pna chfu gb guvf oenapu."""
> +         erghea purpx_crezvffvba("ynhapucnq.Rqvg", frys.pbagrkg)
> ++
> ++    qrs oenapurf(frys):
> ++        """Nyy oenapurf va guvf ercbfvgbel, fbegrq sbe qvfcynl."""
> ++        erghea TvgErsOngpuAnivtngbe(frys, frys.pbagrkg)
> +
> +=== zbqvsvrq svyr 'yvo/yc/pbqr/vagresnprf/tvgers.cl'
> +--- yvo/yc/pbqr/vagresnprf/tvgers.cl	2015-03-19 11:15:48 +0000
> ++++ yvo/yc/pbqr/vagresnprf/tvgers.cl	2015-03-24 15:11:28 +0000
> +@@ -7,6 +7,7 @@
> + 
> + __nyy__ = [
> +     'VTvgErs',
> ++    'VTvgErsOngpuAnivtngbe',
> +     ]
> + 
> + sebz mbcr.vagresnpr vzcbeg (
> +@@ -22,6 +23,7 @@
> + 
> + sebz yc vzcbeg _
> + sebz yc.pbqr.rahzf vzcbeg TvgBowrpgGlcr
> ++sebz yc.freivprf.jroncc.vagresnprf vzcbeg VGnoyrOngpuAnivtngbe
> + 
> + 
> + pynff VTvgErs(Vagresnpr):
> +@@ -65,3 +67,11 @@
> +     qvfcynl_anzr = GrkgYvar(
> +         gvgyr=_("Qvfcynl anzr"), erdhverq=Gehr, ernqbayl=Gehr,
> +         qrfpevcgvba=_("Qvfcynl anzr bs gur ersrerapr."))
> ++
> ++    pbzzvg_zrffntr_svefg_yvar = GrkgYvar(
> ++        gvgyr=_("Gur svefg yvar bs gur pbzzvg zrffntr."),
> ++        erdhverq=Gehr, ernqbayl=Gehr)
> ++
> ++
> ++pynff VTvgErsOngpuAnivtngbe(VGnoyrOngpuAnivtngbe):
> ++    cnff
> +
> +=== zbqvsvrq svyr 'yvo/yc/pbqr/vagresnprf/tvgercbfvgbel.cl'
> +--- yvo/yc/pbqr/vagresnprf/tvgercbfvgbel.cl	2015-03-20 14:17:28 +0000
> ++++ yvo/yc/pbqr/vagresnprf/tvgercbfvgbel.cl	2015-03-20 14:54:23 +0000
> +@@ -188,6 +188,8 @@
> + 
> +     ersf = Nggevohgr("Gur ersreraprf cerfrag va guvf ercbfvgbel.")
> + 
> ++    oenapurf = Nggevohgr("Gur oenapu ersreraprf cerfrag va guvf ercbfvgbel.")
> ++
> +     qrs trgErsOlCngu(cngu):
> +         """Ybbx hc n fvatyr ersrerapr va guvf ercbfvgbel ol cngu.
> + 
> +
> +=== zbqvsvrq svyr 'yvo/yc/pbqr/zbqry/tvgers.cl'
> +--- yvo/yc/pbqr/zbqry/tvgers.cl	2015-03-19 11:15:48 +0000
> ++++ yvo/yc/pbqr/zbqry/tvgers.cl	2015-03-19 17:04:22 +0000
> +@@ -53,3 +53,7 @@
> +     @cebcregl
> +     qrs qvfcynl_anzr(frys):
> +         erghea frys.cngu.fcyvg("/", 2)[-1]
> ++
> ++    @cebcregl
> ++    qrs pbzzvg_zrffntr_svefg_yvar(frys):
> ++        erghea frys.pbzzvg_zrffntr.fcyvg("\a", 1)[0]
> 
> === added file 'lib/lp/testing/data/small.diff'
> --- lib/lp/testing/data/small.diff	1970-01-01 00:00:00 +0000
> +++ lib/lp/testing/data/small.diff	2015-04-09 03:38:19 +0000
> @@ -0,0 +1,14 @@
> +=== zbqvsvrq svyr 'yvo/yc/pbqr/vagresnprf/qvss.cl'
> +--- yvo/yc/pbqr/vagresnprf/qvss.cl      2009-10-01 13:25:12 +0000
> ++++ yvo/yc/pbqr/vagresnprf/qvss.cl      2010-02-02 15:48:56 +0000
> +@@ -121,6 +121,10 @@
> +                 'Gur pbasyvpgf grkg qrfpevovat nal cngu be grkg pbasyvpgf.'),
> +              ernqbayl=Gehr))
> +
> ++    unf_pbasyvpgf = Obby(
> ++        gvgyr=_('Unf pbasyvpgf'), ernqbayl=Gehr,
> ++        qrfpevcgvba=_('Gur cerivrjrq zretr cebqhprf pbasyvpgf.'))
> ++
> +     # Gur fpurzn sbe gur Ersrerapr trgf cngpurq va _fpurzn_pvephyne_vzcbegf.
> +     oenapu_zretr_cebcbfny = rkcbegrq(
> +         Ersrerapr(
> \ No newline at end of file
> 
> === modified file 'lib/lp/testing/factory.py'
> --- lib/lp/testing/factory.py	2015-03-17 15:34:05 +0000
> +++ lib/lp/testing/factory.py	2015-04-09 03:38:19 +0000
> @@ -348,23 +348,6 @@
>  
>  SPACE = ' '
>  
> -DIFF = """\
> -=== zbqvsvrq svyr 'yvo/yc/pbqr/vagresnprf/qvss.cl'
> ---- yvo/yc/pbqr/vagresnprf/qvss.cl      2009-10-01 13:25:12 +0000
> -+++ yvo/yc/pbqr/vagresnprf/qvss.cl      2010-02-02 15:48:56 +0000
> -@@ -121,6 +121,10 @@
> -                 'Gur pbasyvpgf grkg qrfpevovat nal cngu be grkg pbasyvpgf.'),
> -              ernqbayl=Gehr))
> -
> -+    unf_pbasyvpgf = Obby(
> -+        gvgyr=_('Unf pbasyvpgf'), ernqbayl=Gehr,
> -+        qrfpevcgvba=_('Gur cerivrjrq zretr cebqhprf pbasyvpgf.'))
> -+
> -     # Gur fpurzn sbe gur Ersrerapr trgf cngpurq va _fpurzn_pvephyne_vzcbegf.
> -     oenapu_zretr_cebcbfny = rkcbegrq(
> -         Ersrerapr(
> -"""
> -
>  
>  def default_master_store(func):
>      """Decorator to temporarily set the default Store to the master.
> @@ -1536,13 +1519,17 @@
>              BranchSubscriptionNotificationLevel.NOEMAIL, None,
>              CodeReviewNotificationLevel.NOEMAIL, subscribed_by)
>  
> -    def makeDiff(self, diff_text=DIFF):
> -        return ProxyFactory(
> -            Diff.fromFile(StringIO(diff_text), len(diff_text)))
> +    def makeDiff(self, size='small'):
> +        diff_path = os.path.join(os.path.dirname(__file__),
> +                                 'data/{}.diff'.format(size))
> +        with open(os.path.join(diff_path), 'r') as diff:
> +            diff_text = diff.read()
> +            return ProxyFactory(
> +                Diff.fromFile(StringIO(diff_text), len(diff_text)))
>  
>      def makePreviewDiff(self, conflicts=u'', merge_proposal=None,
> -                        date_created=None):
> -        diff = self.makeDiff()
> +                        date_created=None, size='small'):
> +        diff = self.makeDiff(size)
>          if merge_proposal is None:
>              merge_proposal = self.makeBranchMergeProposal()
>          preview_diff = PreviewDiff()
> 


-- 
https://code.launchpad.net/~blr/launchpad/bug-1430597-kb-shortcuts-diff-view/+merge/254313
Your team Launchpad code reviewers is subscribed to branch lp:launchpad.


References