Skip to content

Commit

Permalink
Merge pull request #193 from wbinnssmith/wbinnssmith/limit-highlights
Browse files Browse the repository at this point in the history
Limit the maximum number of highlight markers
  • Loading branch information
richrace authored Mar 17, 2019
2 parents ded1f2a + da2eb3d commit 881e456
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 26 deletions.
4 changes: 4 additions & 0 deletions lib/highlight-selected.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ module.exports =
minimumLength:
type: 'integer'
default: 2
maximumHighlights:
type: 'integer'
default: 500
description: 'For performance purposes, the number of highlights is limited'
timeout:
type: 'integer'
default: 20
Expand Down
77 changes: 51 additions & 26 deletions lib/highlighted-area-view.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -165,37 +165,60 @@ class HighlightedAreaView

highlightSelectionInEditor: (editor, regexSearch, regexFlags, originalEditor) ->
return unless editor?
maximumHighlights = atom.config.get('highlight-selected.maximumHighlights')
return unless this.resultCount < maximumHighlights

markerLayers = @editorToMarkerLayerMap[editor.id]
return unless markerLayers?
markerLayer = markerLayers['visibleMarkerLayer']
markerLayerForHiddenMarkers = markerLayers['selectedMarkerLayer']

editor.scan new RegExp(regexSearch, regexFlags),
(result) =>
newResult = result
if atom.config.get('highlight-selected.onlyHighlightWholeWords')
editor.scanInBufferRange(
new RegExp(escapeRegExp(result.match[1])),
result.range,
(e) -> newResult = e
)

return unless newResult?
@resultCount += 1

if @showHighlightOnSelectedWord(newResult.range, @selections) &&
originalEditor?.id == editor.id
marker = markerLayerForHiddenMarkers.markBufferRange(newResult.range)
@emitter.emit 'did-add-selected-marker', marker
@emitter.emit 'did-add-selected-marker-for-editor',
marker: marker
editor: editor
else
marker = markerLayer.markBufferRange(newResult.range)
@emitter.emit 'did-add-marker', marker
@emitter.emit 'did-add-marker-for-editor',
marker: marker
editor: editor
# HACK: `editor.scan` is a synchronous process which iterates the entire buffer,
# executing a regex against every line and yielding each match. This can be
# costly for very large files with many matches.
#
# While we can and do limit the maximum number of highlight markers,
# `editor.scan` cannot be terminated early, meaning that we are forced to
# pay the cost of iterating every line in the file, running the regex, and
# returning matches, even if we shouldn't be creating any more markers.
#
# Instead, throw an exception. This isn't pretty, but it prevents the
# scan from running to completion unnecessarily.
try
editor.scan new RegExp(regexSearch, regexFlags),
(result) =>
if (this.resultCount >= maximumHighlights)
throw new EarlyTerminationSignal

newResult = result
if atom.config.get('highlight-selected.onlyHighlightWholeWords')
editor.scanInBufferRange(
new RegExp(escapeRegExp(result.match[1])),
result.range,
(e) -> newResult = e
)

return unless newResult?
@resultCount += 1

if @showHighlightOnSelectedWord(newResult.range, @selections) &&
originalEditor?.id == editor.id
marker = markerLayerForHiddenMarkers.markBufferRange(newResult.range)
@emitter.emit 'did-add-selected-marker', marker
@emitter.emit 'did-add-selected-marker-for-editor',
marker: marker
editor: editor
else
marker = markerLayer.markBufferRange(newResult.range)
@emitter.emit 'did-add-marker', marker
@emitter.emit 'did-add-marker-for-editor',
marker: marker
editor: editor
catch error
if error not instanceof EarlyTerminationSignal
# If this is an early termination, just continue on.
throw error

editor.decorateMarkerLayer(markerLayer, {
type: 'highlight',
class: @makeClasses()
Expand Down Expand Up @@ -345,3 +368,5 @@ class HighlightedAreaView

scrollMarkerView = @scrollMarker.scrollMarkerViewForEditor(editor)
scrollMarkerView.destroy()

class EarlyTerminationSignal extends Error

0 comments on commit 881e456

Please sign in to comment.