From c9e0f07a5a4a2f9512872ba416d5f583a007793e Mon Sep 17 00:00:00 2001 From: Damien Mathieu <42@dmathieu.com> Date: Tue, 7 Jan 2014 11:18:15 +0100 Subject: [PATCH] highlight multiple lines We can now highlight multiple lines, adding #L1-L2 to the hash. We can select the ending line with shift + click. Closes travis-ci/travis-ci#1829 --- assets/scripts/app/controllers/build.coffee | 2 +- assets/scripts/app/controllers/job.coffee | 2 +- assets/scripts/app/controllers/repo.coffee | 10 +++ assets/scripts/app/routes.coffee | 5 +- assets/scripts/app/views/log.coffee | 64 ++++++++++++------- .../lib/travis/line_number_parser.coffee | 15 ++++- .../spec/unit/line_number_parser_spec.coffee | 12 ++++ assets/styles/_mixins/colors.sass | 2 + assets/styles/main/log.sass | 2 + 9 files changed, 86 insertions(+), 28 deletions(-) create mode 100644 assets/scripts/spec/unit/line_number_parser_spec.coffee diff --git a/assets/scripts/app/controllers/build.coffee b/assets/scripts/app/controllers/build.coffee index ba99f348..1efa56bd 100644 --- a/assets/scripts/app/controllers/build.coffee +++ b/assets/scripts/app/controllers/build.coffee @@ -2,7 +2,7 @@ Travis.BuildController = Ember.Controller.extend needs: ['repo'] repoBinding: 'controllers.repo.repo' commitBinding: 'build.commit' - lineNumberBinding: 'controllers.repo.lineNumber' + lineNumbersBinding: 'controllers.repo.lineNumbers' currentUserBinding: 'controllers.repo.currentUser' tabBinding: 'controllers.repo.tab' diff --git a/assets/scripts/app/controllers/job.coffee b/assets/scripts/app/controllers/job.coffee index 148dbad7..92e97862 100644 --- a/assets/scripts/app/controllers/job.coffee +++ b/assets/scripts/app/controllers/job.coffee @@ -4,7 +4,7 @@ Travis.JobController = Em.Controller.extend jobBinding: 'controllers.repo.job' repoBinding: 'controllers.repo.repo' commitBinding: 'job.commit' - lineNumberBinding: 'controllers.repo.lineNumber' + lineNumbersBinding: 'controllers.repo.lineNumbers' currentUserBinding: 'controllers.repo.currentUser' tabBinding: 'controllers.repo.tab' diff --git a/assets/scripts/app/controllers/repo.coffee b/assets/scripts/app/controllers/repo.coffee index 88276d71..cbd4fa34 100644 --- a/assets/scripts/app/controllers/repo.coffee +++ b/assets/scripts/app/controllers/repo.coffee @@ -72,3 +72,13 @@ Travis.RepoController = Travis.Controller.extend urlGithub: (-> Travis.Urls.githubRepo(@get('repo.slug')) ).property('repo.slug') + + setLineNumbers: (start, end) -> + lines = [] + index = start + + while index <= (end || start) + lines.push(index) + index++ + + @set('lineNumbers', lines) diff --git a/assets/scripts/app/routes.coffee b/assets/scripts/app/routes.coffee index 0f8186c1..6907527d 100644 --- a/assets/scripts/app/routes.coffee +++ b/assets/scripts/app/routes.coffee @@ -82,7 +82,7 @@ Ember.Route.reopen Travis.Router.reopen transitionTo: -> - this.container.lookup('controller:repo').set('lineNumber', null) + this.container.lookup('controller:repo').set('lineNumbers', []) @_super.apply this, arguments @@ -113,7 +113,8 @@ Travis.ApplicationRoute = Ember.Route.extend Travis.LineNumberParser, setupController: -> @_super.apply this, arguments - this.controllerFor('repo').set('lineNumber', @fetchLineNumber()) + line_numbers = @fetchLineNumbers(document.location.hash) + this.controllerFor('repo').setLineNumbers line_numbers[0], line_numbers[1] Travis.SetupLastBuild = Ember.Mixin.create setupController: -> diff --git a/assets/scripts/app/views/log.coffee b/assets/scripts/app/views/log.coffee index 2bacdfe2..f2216ad1 100644 --- a/assets/scripts/app/views/log.coffee +++ b/assets/scripts/app/views/log.coffee @@ -26,7 +26,7 @@ Travis.reopen console.log 'log view: did insert' if Log.DEBUG @_super.apply this, arguments @createEngine() - @lineNumberDidChange() + @lineNumbersDidChange() willDestroyElement: -> console.log 'log view: will destroy' if Log.DEBUG @@ -63,9 +63,9 @@ Travis.reopen @engine.set(part.number, part.content) @propertyDidChange('limited') - lineNumberDidChange: (-> - @scroll.set(number) if !@get('isDestroyed') && number = @get('controller.lineNumber') - ).observes('controller.lineNumber') + lineNumbersDidChange: (-> + @scroll.set(numbers) if !@get('isDestroyed') && numbers = @get('controller.lineNumbers') + ).observes('controller.lineNumbers') limited: (-> @engine?.limit?.limited @@ -80,22 +80,35 @@ Travis.reopen event.preventDefault() numberLineOnHover: -> - $('#log').on 'mouseenter', 'a', -> - $(@).attr('href', '#L' + ($("#log p:visible").index(@parentNode) + 1)) + $('#log').on 'mouseenter', 'a', (event) -> + hovered = $("#log p:visible").index(@parentNode) + 1 + selected = $("#log p:visible").index($('#log p.highlight')) + 1 + + if event.shiftKey + end = "-L#{hovered}" + start = selected + else + start = hovered + end = '' + + $(@).attr('href', "#L#{start}#{end}") click: (event) -> - if (href = $(event.target).attr('href')) && matches = href?.match(/#L(\d+)$/) - @lineNumberClicked(matches[1]) + if (href = $(event.target).attr('href')) && matches = href?.match(Travis.LineNumberRegex) + lines = [matches[1], matches[3]].sort (a, b) -> a - b + + @lineNumberClicked(lines[0], lines[1]) event.stopPropagation() false else target = $(event.target) target.closest('.fold').toggleClass('open') - lineNumberClicked: (number) -> - path = "#{window.location.pathname}#L#{number}" + lineNumberClicked: (start, end) -> + second_number = if end then "-L#{end}" else '' + path = "#{window.location.pathname}#L#{start}#{second_number}" window.history.pushState({ path: path }, null, path); - @set('controller.lineNumber', number) + @get('controller.controllers.repo').setLineNumbers(start, end) actions: toTop: () -> @@ -105,25 +118,32 @@ Travis.reopen Log.Scroll = -> Log.Scroll.prototype = $.extend new Log.Listener, - set: (number) -> - return unless number - @number = number + set: (numbers) -> + return unless numbers.length > 0 + @numbers = numbers @tryScroll() insert: (log, data, pos) -> - @tryScroll() if @number + @tryScroll() if @numbers true tryScroll: -> - if element = $("#log p:visible")[@number - 1] + @removeHighlights() + @scrollToFirstLine() + + first_line = @numbers[0] - 1 + last_line = @numbers[@numbers.length - 1] + + $('#log').find('p:visible').slice(first_line, last_line).addClass('highlight') + @numbers = undefined + + removeHighlights: -> + $('#log p.highlight').removeClass('highlight') + + scrollToFirstLine: -> + if element = $("#log p:visible")[@numbers[0] - 1] $('#main').scrollTop(0) $('html, body').scrollTop($(element).offset()?.top) # weird, html works in chrome, body in firefox - @highlight(element) - @number = undefined - - highlight: (element) -> - $('#log p.highlight').removeClass('highlight') - $(element).addClass('highlight') # Log.Logger = -> # Log.Logger.prototype = $.extend new Log.Listener, diff --git a/assets/scripts/lib/travis/line_number_parser.coffee b/assets/scripts/lib/travis/line_number_parser.coffee index 2abd54df..8cbc87e2 100644 --- a/assets/scripts/lib/travis/line_number_parser.coffee +++ b/assets/scripts/lib/travis/line_number_parser.coffee @@ -1,3 +1,14 @@ +Travis.LineNumberRegex = /#L(\d+)(-L(\d+))?$/ Travis.LineNumberParser = Ember.Mixin.create - fetchLineNumber: -> - match[1] if match = document.location.hash.match(/#L(\d+)$/) + + fetchLineNumbers: (hash) -> + if match = hash.match(Travis.LineNumberRegex) + start = match[1] + end = match[3] + + if end? + [start, end] + else + [start] + else + [] diff --git a/assets/scripts/spec/unit/line_number_parser_spec.coffee b/assets/scripts/spec/unit/line_number_parser_spec.coffee new file mode 100644 index 00000000..e55e15e1 --- /dev/null +++ b/assets/scripts/spec/unit/line_number_parser_spec.coffee @@ -0,0 +1,12 @@ +object = Ember.Object.extend(Travis.LineNumberParser) +subject = object.create() + +module "Travis.LineNumberParser", + test "without line numbers", -> + deepEqual subject.fetchLineNumbers(''), [] + + test "with a start date only", -> + deepEqual subject.fetchLineNumbers('#L5'), ['5'] + + test "with a start and end dates", -> + deepEqual subject.fetchLineNumbers('#L5-L6'), ['5', '6'] diff --git a/assets/styles/_mixins/colors.sass b/assets/styles/_mixins/colors.sass index e54bf4fa..ec6e5313 100644 --- a/assets/styles/_mixins/colors.sass +++ b/assets/styles/_mixins/colors.sass @@ -23,6 +23,7 @@ $yellow-light-2: #fffcf4 $gray-dark-1: #333 $gray-dark-2: #444 $gray-dark-3: #666 +$gray-dark-4: #777 $gray-medium-1: #999 $gray-medium-2: #aaa $gray-medium-3: #c4cbcc @@ -65,6 +66,7 @@ $color-bg-log: #222222 $color-bg-log-fold: $gray-dark-1 $color-bg-log-hover: $gray-dark-2 $color-bg-log-highlight: $gray-dark-3 +$color-bg-log-fold-highlight: $gray-dark-4 $color-bg-slider: $slate-blue-3 $color-bg-left: $gray-light-4 $color-bg-list-odd: $white diff --git a/assets/styles/main/log.sass b/assets/styles/main/log.sass index 2e0ad5ff..d5793a54 100644 --- a/assets/styles/main/log.sass +++ b/assets/styles/main/log.sass @@ -57,6 +57,8 @@ pre#log // &.active p:first-of-type background: $color-bg-log-fold inline-image('ui/log.fold.open.2.png') no-repeat 8px 3px + &.highlight + background-color: $color-bg-log-fold-highlight &:not(.open) p:first-of-type visibility: visible