From c8a21cdcf55e9e8cbaa098ff43800e61c6df7b31 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Wed, 12 Jul 2017 09:25:39 +0100 Subject: [PATCH 1/5] WIP: sort definite real commands from possible incidentals --- .../auto-complete/SuggestionManager.coffee | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/SuggestionManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/SuggestionManager.coffee index e415550253..d147119d8d 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/SuggestionManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/SuggestionManager.coffee @@ -1,7 +1,7 @@ define [], () -> class Parser - constructor: (@doc) -> + constructor: (@doc, @prefix) -> parse: () -> # Safari regex is super slow, freezes browser for minutes on end, @@ -10,13 +10,14 @@ define [], () -> if window?._ide?.browserIsSafari limit = 100 - commands = [] + realCommands = [] + incidentalCommands = [] seen = {} iterations = 0 while command = @nextCommand() iterations += 1 if limit && iterations > limit - return commands + return realCommands docState = @doc @@ -31,12 +32,23 @@ define [], () -> commandHash = "#{command}\\#{optionalArgs}\\#{args}" if !seen[commandHash]? seen[commandHash] = true - commands.push [command, optionalArgs, args] + + # skip the first occurence of the current command at the cursor + if @prefix? && "\\#{command}" == @prefix + incidentalCommands.push [command, optionalArgs, args] + else + realCommands.push [command, optionalArgs, args] # Reset to before argument to handle nested commands @doc = docState - return commands + # check incidentals + if incidentalCommands.length > 1 + bestMatch = incidentalCommands.sort((a, b) => a[1]+a[2] < b[1]+b[2])[0] + realCommands.push bestMatch + + window.I = incidentalCommands + return realCommands # Ignore single letter commands since auto complete is moot then. commandRegex: /\\([a-zA-Z][a-zA-Z]+)/ @@ -46,7 +58,8 @@ define [], () -> if i == -1 return false else - match = @doc.match(@commandRegex)[1] + M = @doc.match(@commandRegex) + match = M[1] @doc = @doc.substr(i + match.length + 1) return match @@ -78,12 +91,12 @@ define [], () -> class SuggestionManager getCompletions: (editor, session, pos, prefix, callback) -> doc = session.getValue() - parser = new Parser(doc) + parser = new Parser(doc, prefix) commands = parser.parse() completions = [] for command in commands caption = "\\#{command[0]}" - score = 50 + score = if caption == prefix then 99 else 50 snippet = caption i = 1 _.times command[1], () -> @@ -94,13 +107,12 @@ define [], () -> snippet += "{${#{i}}}" caption += "{}" i++ - unless caption == prefix - completions.push { - caption: caption - snippet: snippet - meta: "cmd" - score: score - } + completions.push { + caption: caption + snippet: snippet + meta: "cmd" + score: score + } callback null, completions From 952a765235db76384d2af0cba1653c17b4409c4f Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Wed, 12 Jul 2017 11:33:45 +0100 Subject: [PATCH 2/5] Inteligently rank exact match highest --- .../auto-complete/SuggestionManager.coffee | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/SuggestionManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/SuggestionManager.coffee index d147119d8d..250590e4b4 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/SuggestionManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/SuggestionManager.coffee @@ -10,7 +10,10 @@ define [], () -> if window?._ide?.browserIsSafari limit = 100 + # fully formed commands realCommands = [] + # commands which match the prefix exactly, + # and could be partially typed or malformed incidentalCommands = [] seen = {} iterations = 0 @@ -30,24 +33,22 @@ define [], () -> args++ commandHash = "#{command}\\#{optionalArgs}\\#{args}" - if !seen[commandHash]? - seen[commandHash] = true - # skip the first occurence of the current command at the cursor - if @prefix? && "\\#{command}" == @prefix - incidentalCommands.push [command, optionalArgs, args] - else + if @prefix? && "\\#{command}" == @prefix + incidentalCommands.push [command, optionalArgs, args] + else + if !seen[commandHash]? + seen[commandHash] = true realCommands.push [command, optionalArgs, args] # Reset to before argument to handle nested commands @doc = docState - # check incidentals + # check incidentals, see if we should pluck out a match if incidentalCommands.length > 1 bestMatch = incidentalCommands.sort((a, b) => a[1]+a[2] < b[1]+b[2])[0] realCommands.push bestMatch - window.I = incidentalCommands return realCommands # Ignore single letter commands since auto complete is moot then. @@ -58,8 +59,7 @@ define [], () -> if i == -1 return false else - M = @doc.match(@commandRegex) - match = M[1] + match = @doc.match(@commandRegex)[1] @doc = @doc.substr(i + match.length + 1) return match From 75b0e0cf51531d9143a6a22c57cdabcefeb742c9 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Thu, 13 Jul 2017 10:22:51 +0100 Subject: [PATCH 3/5] Don't offer autocomplete for double-backslash --- .../aceEditor/auto-complete/AutoCompleteManager.coffee | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee index 7aca56d9bc..030b2d4abf 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee @@ -128,6 +128,11 @@ define [ if lineUpToCursor.match(/.*%.*/) return lastCharIsBackslash = lineUpToCursor.slice(-1) == "\\" + lastTwoCharsAreBackslash = lineUpToCursor.slice(-2) == "\\\\" + # Don't offer autocomplete on double-backslash + if lastTwoCharsAreBackslash + @editor?.completer?.detach?() + return commandFragment = getLastCommandFragment(lineUpToCursor) commandName = getCommandNameFromFragment(commandFragment) if commandName in ['begin', 'end'] From f66982dd8b00cb87916b3e2b075e0b2c76610141 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Thu, 13 Jul 2017 10:23:45 +0100 Subject: [PATCH 4/5] Consistently delete back to last backslash --- .../auto-complete/AutoCompleteManager.coffee | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee index 030b2d4abf..5a8ad66a2c 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee @@ -188,8 +188,22 @@ define [ leftRange = _.clone(range) rightRange = _.clone(range) # trim to left of cursor - leftRange.start.column -= completions.filterText.length; - editor.session.remove(leftRange); + lineUpToCursor = editor.getSession().getTextRange( + new Range( + range.start.row, + 0, + range.start.row, + range.start.column, + ) + ) + # Delete back to last backslash, as appropriate + lastBackslashIndex = lineUpToCursor.lastIndexOf('\\') + if lastBackslashIndex != -1 + leftRange.start.column = lastBackslashIndex + else + leftRange.start.column -= completions.filterText.length + editor.session.remove(leftRange) + # look at text after cursor lineBeyondCursor = editor.getSession().getTextRange( new Range( rightRange.start.row, From 70e5279ba20c09fed5648616ad0cea087f0c5f00 Mon Sep 17 00:00:00 2001 From: Shane Kilkelly Date: Fri, 14 Jul 2017 13:52:18 +0100 Subject: [PATCH 5/5] Don't autocomplete for commands like `\\`, `\[`, `\:`, etc --- .../aceEditor/auto-complete/AutoCompleteManager.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee index 5a8ad66a2c..c320266a5a 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee +++ b/services/web/public/coffee/ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager.coffee @@ -128,9 +128,9 @@ define [ if lineUpToCursor.match(/.*%.*/) return lastCharIsBackslash = lineUpToCursor.slice(-1) == "\\" - lastTwoCharsAreBackslash = lineUpToCursor.slice(-2) == "\\\\" - # Don't offer autocomplete on double-backslash - if lastTwoCharsAreBackslash + lastTwoChars = lineUpToCursor.slice(-2) + # Don't offer autocomplete on double-backslash, backslash-colon, etc + if lastTwoChars.match(/^\\[^a-z]$/) @editor?.completer?.detach?() return commandFragment = getLastCommandFragment(lineUpToCursor)