<commit_before>define [
	"ace/ace"
	"ace/mode/latex"
	"ace/range"
	"moment"
	"libs/backbone"
], (Ace, LatexMode, Range, moment)->
	DiffView = Backbone.View.extend
		initialize: () ->
			@model.on "change:diff", () => @render()
			@render()

		render: ->
			diff = @model.get("diff")
			return unless diff?
			@createAceEditor()
			@aceEditor.setValue(@getPlainDiffContent())
			@aceEditor.clearSelection()
			@$ace = $(@aceEditor.renderer.container).find(".ace_scroller")
			@insertMarkers()
			@insertNameTag()
			@insertMoreChangeLabels()
			@bindToScrollEvents()
			@scrollToFirstChange()
			return @

		destroy: () ->
			@$editor?.remove()

		createAceEditor: () ->
			@$el.empty()
			@$editor = $("<div/>")
			@$el.append(@$editor)
			@aceEditor = Ace.edit(@$editor[0])
			@aceEditor.setTheme("ace/theme/#{window.userSettings.theme}")
			@aceEditor.setReadOnly true
			@aceEditor.setShowPrintMargin(false)
			session = @aceEditor.getSession()
			session.setMode(new LatexMode.Mode())
			session.setUseWrapMode(true)

			@aceEditor.on "mousemove", (e) =>
				position = @aceEditor.renderer.screenToTextCoordinates(e.clientX, e.clientY)
				e.position = position
				@updateVisibleNames(e)

		bindToScrollEvents: () ->
			@aceEditor.getSession().on "changeScrollTop", (e) =>
				@updateMoreChangeLabels()

		getPlainDiffContent: () ->
			content = ""
			for entry in @model.get("diff") or []
				content += entry.u or entry.i or entry.d or ""
			return content

		insertMarkers: () ->
			row    = 0
			column = 0
			@entries = []
			for entry, i in @model.get("diff") or []
				content = entry.u or entry.i or entry.d
				content ||= ""
				lines   = content.split("\n")
				startRow    = row
				startColumn = column
				if lines.length > 1
					endRow    = startRow + lines.length - 1
					endColumn = lines[lines.length - 1].length
				else
					endRow    = startRow
					endColumn = startColumn + lines[0].length
				row    = endRow
				column = endColumn

				range = new Range.Range(
					startRow, startColumn, endRow, endColumn
				)
				entry.range = range
				@addMarker(range, entry)
				if entry.i? or entry.d?
					@entries.push entry

		addMarker: (range, entry) ->
			session  = @aceEditor.getSession()
			markerBackLayer = @aceEditor.renderer.$markerBack
			markerFrontLayer = @aceEditor.renderer.$markerFront
			lineHeight = @aceEditor.renderer.lineHeight
			if entry.i? or entry.d?
				hue = entry.meta.user.hue()
				if entry.i?
					@_addMarkerWithCustomStyle session, markerBackLayer, range, "inserted-change-background", false, """
						background-color : hsl(#{hue}, 70%, 85%);
					"""
				if entry.d?
					@_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-background", false, """
						background-color : hsl(#{hue}, 70%, 95%);
					"""
					@_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-foreground", true, """
						height: #{Math.round(lineHeight/2) - 1}px;
						border-bottom: 2px solid hsl(#{hue}, 70%, 40%);
					"""

		_addMarkerWithCustomStyle: (session, markerLayer, range, klass, foreground, style) ->
			session.addMarker range, klass, (html, range, left, top, config) ->
				if range.isMultiLine()
					markerLayer.drawTextMarker(html, range, klass, config, style)
				else
					markerLayer.drawSingleLineMarker(html, range, "#{klass} ace_start", config, 0, style)
			, foreground

		insertNameTag: () ->
			@$nameTagEl = $("<div class='change-name-marker'></div>")
			@$nameTagEl.css({
				position: "absolute"
			})
			@$nameTagEl.hide()
			@$ace.append(@$nameTagEl)

		insertMoreChangeLabels: () ->
			@$changesBefore = $("<a class='changes-before' href='#'><span></span> <i class='icon-arrow-up'></a>")
			@$changesAfter = $("<a class='changes-after' href='#'><span></span> <i class='icon-arrow-down'></a>")
			@$ace.append(@$changesBefore)
			@$ace.append(@$changesAfter)
			@$changesBefore.on "click", () =>
				@gotoLastHiddenChangeBefore()
			@$changesAfter.on "click", () =>
				@gotoFirstHiddenChangeAfter()
			@updateMoreChangeLabels()

		scrollToFirstChange: () ->
			@aceEditor.scrollToLine(0)
			setTimeout () =>
				if @entries? and @entries[0]?
					row = @entries[0].range.start.row
					@aceEditor.scrollToLine(row, true, false)
			, 10

		_drawNameTag: (entry, position) ->
			@$nameTagEl.show()
			
			if entry.i?
				text = "Added by #{entry.meta.user.name()}"
			else if entry.d?
				text = "Deleted by #{entry.meta.user.name()}"
			date = moment(parseInt(entry.meta.end_ts, 10)).format("Do MMM YYYY, h:mm a")
			text += " on #{date}"
			@$nameTagEl.text(text)

			position = @aceEditor.renderer.textToScreenCoordinates(position.row, position.column)
			offset = @$ace.offset()
			position.pageX = position.pageX - offset.left
			position.pageY = position.pageY - offset.top
			height = @$ace.height()

			hue = entry.meta.user.hue()
			css = {
				"background-color" : "hsl(#{hue}, 70%, 90%)";
			}

			if position.pageX + @$nameTagEl.width() < @$ace.width()
				css["left"] = position.pageX
				css["right"] = "auto"
			else
				css["right"] = 0
				css["left"] = "auto"

			if position.pageY > 2 * @$nameTagEl.height()
				css["bottom"] = height - position.pageY
				css["top"] = "auto"
			else
				css["top"] = position.pageY + @aceEditor.renderer.lineHeight
				css["bottom"] = "auto"

			@$nameTagEl.css css

		_hideNameTag: () ->
			@$nameTagEl.hide()

		updateVisibleNames: (e) ->
			visibleName = false
			for entry in @entries or []
				if entry.range.contains(e.position.row, e.position.column)
					@_drawNameTag(entry, e.position)
					visibleName = true
					break
			if !visibleName
				@_hideNameTag()

		updateMoreChangeLabels: () ->
			return if !@$changesBefore or !@$changesAfter
			setTimeout () =>
				firstRow = @aceEditor.getFirstVisibleRow()
				lastRow = @aceEditor.getLastVisibleRow()
				changesBefore = 0
				changesAfter = 0
				@lastHiddenChangeBefore = null
				@firstHiddenChangeAfter = null
				for entry in @entries or []
					if entry.range.start.row < firstRow
						changesBefore += 1
						@lastHiddenChangeBefore = entry
					if entry.range.end.row > lastRow
						changesAfter += 1
						@firstHiddenChangeAfter ||= entry

				if changesBefore > 0
					@$changesBefore.find("span").text("#{changesBefore} more change#{if changesBefore > 1 then "s" else ""} above")
					@$changesBefore.show()
				else
					@$changesBefore.hide()
				if changesAfter > 0
					@$changesAfter.find("span").text("#{changesAfter} more change#{if changesAfter > 1 then "s" else ""} below")
					@$changesAfter.show()
				else
					@$changesAfter.hide()
			, 100

		gotoLastHiddenChangeBefore: () ->
			return if !@lastHiddenChangeBefore
			@aceEditor.scrollToLine(@lastHiddenChangeBefore.range.start.row, true, false)

		gotoFirstHiddenChangeAfter: () ->
			return if !@firstHiddenChangeAfter
			@aceEditor.scrollToLine(@firstHiddenChangeAfter.range.end.row, true, false)

		resize: () ->
			@aceEditor.resize()

	return DiffView

<commit_msg>Use different color schemes for dark or light editor schemes<commit_after>define [
	"ace/ace"
	"ace/mode/latex"
	"ace/range"
	"moment"
	"libs/backbone"
], (Ace, LatexMode, Range, moment)->
	DiffView = Backbone.View.extend
		initialize: () ->
			@model.on "change:diff", () => @render()
			@render()

		render: ->
			diff = @model.get("diff")
			return unless diff?
			@createAceEditor()
			@aceEditor.setValue(@getPlainDiffContent())
			@aceEditor.clearSelection()
			@$ace = $(@aceEditor.renderer.container).find(".ace_scroller")
			@insertMarkers()
			@insertNameTag()
			@insertMoreChangeLabels()
			@bindToScrollEvents()
			@scrollToFirstChange()
			return @

		destroy: () ->
			@$editor?.remove()

		createAceEditor: () ->
			@$el.empty()
			@$editor = $("<div/>")
			@$el.append(@$editor)
			@aceEditor = Ace.edit(@$editor[0])
			@aceEditor.setTheme("ace/theme/#{window.userSettings.theme}")
			@aceEditor.setReadOnly true
			@aceEditor.setShowPrintMargin(false)
			session = @aceEditor.getSession()
			session.setMode(new LatexMode.Mode())
			session.setUseWrapMode(true)

			@aceEditor.on "mousemove", (e) =>
				position = @aceEditor.renderer.screenToTextCoordinates(e.clientX, e.clientY)
				e.position = position
				@updateVisibleNames(e)

		bindToScrollEvents: () ->
			@aceEditor.getSession().on "changeScrollTop", (e) =>
				@updateMoreChangeLabels()

		getPlainDiffContent: () ->
			content = ""
			for entry in @model.get("diff") or []
				content += entry.u or entry.i or entry.d or ""
			return content

		insertMarkers: () ->
			row    = 0
			column = 0
			@entries = []
			for entry, i in @model.get("diff") or []
				content = entry.u or entry.i or entry.d
				content ||= ""
				lines   = content.split("\n")
				startRow    = row
				startColumn = column
				if lines.length > 1
					endRow    = startRow + lines.length - 1
					endColumn = lines[lines.length - 1].length
				else
					endRow    = startRow
					endColumn = startColumn + lines[0].length
				row    = endRow
				column = endColumn

				range = new Range.Range(
					startRow, startColumn, endRow, endColumn
				)
				entry.range = range
				@addMarker(range, entry)
				if entry.i? or entry.d?
					@entries.push entry

		addMarker: (range, entry) ->
			session  = @aceEditor.getSession()
			markerBackLayer = @aceEditor.renderer.$markerBack
			markerFrontLayer = @aceEditor.renderer.$markerFront
			lineHeight = @aceEditor.renderer.lineHeight

			dark = @_isDarkTheme()

			if entry.i? or entry.d?
				hue = entry.meta.user.hue()
				if entry.i?
					if dark
						style = "background-color : hsl(#{hue}, 100%, 28%);"
					else
						style = "background-color : hsl(#{hue}, 70%, 85%);"
					@_addMarkerWithCustomStyle session, markerBackLayer, range, "inserted-change-background", false, style
				if entry.d?
					if dark
						bgStyle = "background-color: hsl(#{hue}, 100%, 20%);"
						fgStyle = "border-bottom: 2px solid hsl(#{hue}, 100%, 60%);"
					else
						bgStyle = "background-color: hsl(#{hue}, 70%, 95%);"
						fgStyle = "border-bottom: 2px solid hsl(#{hue}, 70%, 40%);"
					fgStyle += "; height: #{Math.round(lineHeight/2) - 1}px;"
					@_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-background", false, bgStyle
					@_addMarkerWithCustomStyle session, markerBackLayer, range, "deleted-change-foreground", true, fgStyle

		_addMarkerWithCustomStyle: (session, markerLayer, range, klass, foreground, style) ->
			session.addMarker range, klass, (html, range, left, top, config) ->
				if range.isMultiLine()
					markerLayer.drawTextMarker(html, range, klass, config, style)
				else
					markerLayer.drawSingleLineMarker(html, range, "#{klass} ace_start", config, 0, style)
			, foreground

		_isDarkTheme: () ->
			rgb = $(".ace_editor").css("background-color");
			[m, r, g, b] = rgb.match(/rgb\(([0-9]+), ([0-9]+), ([0-9]+)\)/)
			r = parseInt(r, 10)
			g = parseInt(g, 10)
			b = parseInt(b, 10)
			return r + g + b < 3 * 128

		insertNameTag: () ->
			@$nameTagEl = $("<div class='change-name-marker'></div>")
			@$nameTagEl.css({
				position: "absolute"
			})
			@$nameTagEl.hide()
			@$ace.append(@$nameTagEl)

		insertMoreChangeLabels: () ->
			@$changesBefore = $("<a class='changes-before' href='#'><span></span> <i class='icon-arrow-up'></a>")
			@$changesAfter = $("<a class='changes-after' href='#'><span></span> <i class='icon-arrow-down'></a>")
			@$ace.append(@$changesBefore)
			@$ace.append(@$changesAfter)
			@$changesBefore.on "click", () =>
				@gotoLastHiddenChangeBefore()
			@$changesAfter.on "click", () =>
				@gotoFirstHiddenChangeAfter()
			@updateMoreChangeLabels()

		scrollToFirstChange: () ->
			@aceEditor.scrollToLine(0)
			setTimeout () =>
				if @entries? and @entries[0]?
					row = @entries[0].range.start.row
					@aceEditor.scrollToLine(row, true, false)
			, 10

		_drawNameTag: (entry, position) ->
			@$nameTagEl.show()
			
			if entry.i?
				text = "Added by #{entry.meta.user.name()}"
			else if entry.d?
				text = "Deleted by #{entry.meta.user.name()}"
			date = moment(parseInt(entry.meta.end_ts, 10)).format("Do MMM YYYY, h:mm a")
			text += " on #{date}"
			@$nameTagEl.text(text)

			position = @aceEditor.renderer.textToScreenCoordinates(position.row, position.column)
			offset = @$ace.offset()
			position.pageX = position.pageX - offset.left
			position.pageY = position.pageY - offset.top
			height = @$ace.height()

			hue = entry.meta.user.hue()
			if @_isDarkTheme()
				css = { "background-color" : "hsl(#{hue}, 100%, 20%)"; }
			else
				css = { "background-color" : "hsl(#{hue}, 70%, 90%)"; }

			if position.pageX + @$nameTagEl.width() < @$ace.width()
				css["left"] = position.pageX
				css["right"] = "auto"
			else
				css["right"] = 0
				css["left"] = "auto"

			if position.pageY > 2 * @$nameTagEl.height()
				css["bottom"] = height - position.pageY
				css["top"] = "auto"
			else
				css["top"] = position.pageY + @aceEditor.renderer.lineHeight
				css["bottom"] = "auto"

			@$nameTagEl.css css

		_hideNameTag: () ->
			@$nameTagEl?.hide()

		updateVisibleNames: (e) ->
			visibleName = false
			for entry in @entries or []
				if entry.range.contains(e.position.row, e.position.column)
					@_drawNameTag(entry, e.position)
					visibleName = true
					break
			if !visibleName
				@_hideNameTag()

		updateMoreChangeLabels: () ->
			return if !@$changesBefore or !@$changesAfter
			setTimeout () =>
				firstRow = @aceEditor.getFirstVisibleRow()
				lastRow = @aceEditor.getLastVisibleRow()
				changesBefore = 0
				changesAfter = 0
				@lastHiddenChangeBefore = null
				@firstHiddenChangeAfter = null
				for entry in @entries or []
					if entry.range.start.row < firstRow
						changesBefore += 1
						@lastHiddenChangeBefore = entry
					if entry.range.end.row > lastRow
						changesAfter += 1
						@firstHiddenChangeAfter ||= entry

				if changesBefore > 0
					@$changesBefore.find("span").text("#{changesBefore} more change#{if changesBefore > 1 then "s" else ""} above")
					@$changesBefore.show()
				else
					@$changesBefore.hide()
				if changesAfter > 0
					@$changesAfter.find("span").text("#{changesAfter} more change#{if changesAfter > 1 then "s" else ""} below")
					@$changesAfter.show()
				else
					@$changesAfter.hide()
			, 100

		gotoLastHiddenChangeBefore: () ->
			return if !@lastHiddenChangeBefore
			@aceEditor.scrollToLine(@lastHiddenChangeBefore.range.start.row, true, false)

		gotoFirstHiddenChangeAfter: () ->
			return if !@firstHiddenChangeAfter
			@aceEditor.scrollToLine(@firstHiddenChangeAfter.range.end.row, true, false)

		resize: () ->
			@aceEditor.resize()

	return DiffView


{'fraction_non_alphanumeric': 0.1604102564102564, 'fraction_numerical': 0.008957264957264958, 'mean_word_length': 3.393511565034545, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 100, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2272274', 'n_tokens_mistral': 6077, 'n_tokens_neox': 4896, 'n_words': 998}