Toggling of the display of whitespace-only changes.

Review Request #899 — Created June 18, 2009 and submitted

Information

Review Board SVN (deprecated)

Reviewers

This patch adds a basic infrastructure to adding metadata to diff in a line/chunk/file level.
It also implements the detection of whitespace-only changes in diff, and adds a button to the diff viewer to toggle between whitespace visible and highlighted, or hidden and regular.

As a design decision I choose not to collapse a chunk that consisted only of whitespace changes, as it would create an inconsistency with chunks that mix both whitespace and regular changes.
For mixed chunks, the lines that contain only whitespace are set to the regular background, making the visualization better.
I also decided not to move the thin gray lines, that delimit a chunk, in cases of mixed chunks were the whitespace-only section was at the beginning or at the end, as I thought this could cause confusion to the user, to suddenly see a chunk shrink.
For whole chunks, on the other hand, I thought it would be better to hide everything, an so I did.

As all those decisions were pretty arbitrary, I'd really like some input about them.

I also decided to post this patch without unit test for it, as then we can review while I do the unit testing.
Ran all unit tests currenly available, without a breakage.
Applied patch in a production system, with no breakage of existing reviews.
Tested on IE 7, Chrome, Firefox 3.5 and 3.0 and Safari 4.0.

A Unit test for this is needed and will be provided in a following update.
edufelipe
david
  1. Please add screenshots to your review request.
  2. /trunk/reviewboard/diffviewer/diffutils.py (Diff revision 2)
     
     
     
    I'd prefer if you could make another function that wraps diff_line and use it in the map() above. This way we only have to iterate through the lines once instead of twice.
    1. Ok, will do. I didn't actually like the way it looked with a function in map(), but I'll post a patch and let you be the judge.
  3. Can you rename this "opcodes_with_metadata"?
  4. The grammar in this comment is wrong. "this whole thing"?
  5. /trunk/reviewboard/diffviewer/diffutils.py (Diff revision 2)
     
     
     
     
     
    You're iterating over this thing 3 times.
    1. Over what thing? All opcodes? We'll, it will get worse with move detection.
      It actually iterates twice over the groups (once for creating and another time for separating the replace, and once again over the replaces. The whitespace detection could be done in a single pass, move detection can't.
  6. Add spaces between parameters:
    
    for i, j in zip(xrange(i1, i2), xrange(j1, j2)):
  7. Missing space before the second "differ"
  8. /trunk/reviewboard/diffviewer/diffutils.py (Diff revision 2)
     
     
     
    And here's a 4th iteration, but this one is a generator. If you can fold all of these loops in together and keep the yield, it'll make it all much more efficient.
    1. And also makes impossible to detect moves. Then again, the only way to detect a move is if we have all the groups information, simply yielding won't do the trick. You'll see what I'm talking about when I post the move patch.
      
      Thinking about it there might be a way of doing this single pass. Will look into it.
  9. The way you're using this "num_whitespace_chunks" variable is very odd. It seems to be a negative count of non-whitespace chunks, from my reading.
    
    Here's how I'd write it:
    
    file['whitespace_only'] = True
    for j, chunk in enumerate(file['chunks']):
        chunk['index'] = j
        if chunk['change'] != 'equal':
            file['changed_chunks'].append(chunk)
            if not chunk['meta'].get('whitespace_chunk', False):
                file['whitespace_only'] = False
  10. These should only be indented 4 spaces.
  11. Add an extra blank line here.
  12. This style should be in the .css file for the class.
  13. 
      
CM
  1. hi hello
  2. Better give acomment
  3. 
      
edufelipe
edufelipe
chipx86
  1. 
      
  2. This doesn't really describe the function. Might be better as a comment.
    
    Also, "Access"
    1. I did not document the function, just commented on the fact that it is a closure. Will change it to a comment, and turn my spellchecker on for Docstrings.
    2. """comments""" at the top of a function act as function documentation in generated docs and Python's help().
  3. Trailing whitespace.
    
    I don't know that the comment is really necessary.
  4. "WS" -> "whitespace"
    1. Sorry, was meant as an internal comment, that I did not review.
  5. Space after the :
    
    Also, on the comments, there should be a space after #, and the comment should end with a period.
  6. Space between i, j
  7. Space on both sides of +
  8. Please add a documentation comment above this describing the function.
  9. Since we reference table.sidebyside instances many times, we should store the result of $("table.sidebyside") in a variable and reference that variable for all other uses.
  10. Can you put comments on their own lines? With a blank line preceding them.
  11. Blank line before this.
  12. Two blank lines here.
  13. Rather than having onclick, I'd prefer that diffviewer.js register these actions for these links. You can give them IDs to reference them.
    1. I also prefer, as it is the jQuery way. But you set onclicks onto other things, so I was confused. But I'll change it.
    2. Yeah, I need to fix the rest of those at some point. We used to have a lot, and most are gone now.
  14. 
      
edufelipe
chipx86
  1. This is looking awesome. A few more things I noticed and then I think it'll be ready to commit! :)
  2. "accesses"
    1. Spellcheck was on. Apparently it doesn't know grammar (and neither do I) :(
  3. /trunk/reviewboard/diffviewer/diffutils.py (Diff revision 4)
     
     
     
     
     
    Contents of the dictionary should be indented 4 spaces from the return statement.
    1. What about the closing brace? Should it be inline with the return?
  4. Since we only ever define this data in one spot, just do it inline here.
  5. Since we only ever append the group in one place, we can instead yield directly here, which will prevent one more loop, improving efficiency.
    1. Well, it might be true for this patch, but in the move we append in several places, so this code actually is necessary. I could remove it from this patch and put it only on the move one, if that's what you want.
  6. Trailing whitespace.
  7. 
      
edufelipe
david
  1. 
      
  2. This should move outside the for loop, so we avoid compiling it every iteration.
  3. Other than that, this change looks great. Come talk to us on IRC when you get a chance so we can set up commit access.
edufelipe
Review request changed