New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial Implementation of Autocomplete #77
Conversation
fixed the formatting in the autobox
added some comments
The autocomplete box does show up unless there exists a ( in front of the word
… being currently typed vs one that is already complete
Great work on this! I started my new job yesterday, so my time's more limited now, but I'll try to get this reviewed this weekend |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've left some comments on this, mostly style-related. Feel free to disagree with my suggestions if you have a good reason for leaving them as is (just reply to the particular comment(s) letting me know).
One addition I'd recommend would be to add something about this feature to the Other Useful Commands
section of the opening message. You could even add a button that users could click to enable it.
Eventually, I'd like to have this turned on by default, but I think we need some special casing around certain special forms before we do that (this should be done in a separate PR though).
I link to sections in Effective Dart a few times in my review. You don't need to take it as gospel, but I recommend reading through it and keeping it in mind when working. Feel free to correct my code to conform with it too, as there are definitely some places (particularly in older sections) where I don't.
lib/src/web_ui/code_input.dart
Outdated
class CodeInput { | ||
Element element; | ||
//Create an element that contains possible autcomplete options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what this comment is describing exactly. If there's a better phrasing, then use that; otherwise I think it's fine to omit this comment.
Also, style-wise, it's preferred to have a space between //
or ///
and the actual start of the comment (e.g. // Create
)
lib/src/web_ui/code_input.dart
Outdated
|
||
Function(String code) runCode; | ||
Function(int parens) parenListener; | ||
|
||
CodeInput(Element log, this.runCode, {this.parenListener}) { | ||
CodeInput(Element log, this.runCode, Frame env, {this.parenListener}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to keep CodeInput
separate from the interpreter, so I'd rather not have a Frame
passed in here.
I'd recommend calling allDocumentedForms
in the Repl and passing wordToDocs
in here directly.
lib/src/web_ui/code_input.dart
Outdated
class CodeInput { | ||
Element element; | ||
//Create an element that contains possible autcomplete options | ||
Element _autoBox; | ||
Element _wrapperAutoBox; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Effective Dart advises that the most descriptive noun should generally go last in a variable name.
I think _autoBoxWrapper
is cleaner here.
lib/src/web_ui/repl.dart
Outdated
@@ -38,6 +37,12 @@ class Repl { | |||
status = SpanElement()..classes = ['repl-status']; | |||
container.append(status); | |||
buildNewInput(); | |||
if (window.localStorage.containsKey('autocomplete')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To maintain consistency with the rest of the project, prefix this property with #
Background:
The old interpreter had some data stored under user-chosen properties. I needed a way to keep the user from modifying the interpreter's own internal state, so I prefixed all of my properties with a #
, since the character is not allowed in Scheme symbols. I then carried this practice over to the new interpreter.
Eventually (probably as part of #48), I'd like to set up some sort of proper namespacing for local storage (or maybe just switch to IndexedDB), but for now, I'd like to keep new interpreter state properties consistent.
lib/src/web_ui/repl.dart
Outdated
@@ -38,6 +37,12 @@ class Repl { | |||
status = SpanElement()..classes = ['repl-status']; | |||
container.append(status); | |||
buildNewInput(); | |||
if (window.localStorage.containsKey('autocomplete')) { | |||
String val = window.localStorage['autocomplete']; | |||
if (val == 't') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we can't use actual booleans here due to limitations of localStorage, I'd prefer to use more descriptive properties here like disabled
and enabled
.
} else if (nextOpen == -1 || nextClose == -1 || nextOpen < nextClose) { | ||
//Assuming the word is right after the parens | ||
List splitRef = | ||
refLine.substring(strIndex + 1).split(RegExp("[ ()]+")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what this regular expression is actually doing. I recommend including a comment describing the meaning whenever you use all but the most trivial regexes, since they are notoriously difficult to understand.
lib/src/web_ui/code_input.dart
Outdated
//Find the text to the left of where the typing cursor currently is | ||
int cursorPos = findPosition(element, window.getSelection().getRangeAt(0)); | ||
List<String> inputText = | ||
element.text.substring(0, cursorPos).split(RegExp("[(]+")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This regex should probably be commented too
lib/src/web_ui/code_input.dart
Outdated
//Find the last word that was being typed | ||
int currLength = 0; | ||
List output = _currOp(element.text, cursorPos); | ||
List output2 = _currOp(element.text, cursorPos, 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a comment explaining the difference between output
and output2
?
lib/src/web_ui/code_input.dart
Outdated
int currLength = 0; | ||
List output = _currOp(element.text, cursorPos); | ||
List output2 = _currOp(element.text, cursorPos, 2); | ||
String findMatch = output[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noun phrases are generally preferred for non-boolean variables.
A better name would perhaps be foundMatch
or just match
lib/src/web_ui/code_input.dart
Outdated
List output = _currOp(element.text, cursorPos); | ||
List output2 = _currOp(element.text, cursorPos, 2); | ||
String findMatch = output[0]; | ||
bool fullWord = output[1]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise, Dart prefers that booleans are named with a form of "to be" most of the time.
isFullWord
would probably be better here.
Thanks for reviewing this! I'll be sure to get working on these things this week and I'll also read through Effective Dart. |
Sorry it took me so long to get to this. I think I fixed most of the styling issues and also added a blurb about it in the "Other Useful Commands" section. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, aside from the one nit. Feel free to squash and merge once that's fixed. Great work!
lib/src/web_ui/code_input.dart
Outdated
@@ -14,22 +17,35 @@ const List<SchemeSymbol> noIndentForms = [ | |||
SchemeSymbol("define-macro") | |||
]; | |||
|
|||
bool _isEnabledAutocomplete = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: _isAutocompleteEnabled
is probably a better name here
Thanks for reviewing this! I'll try to work on getting this to work better for some of the special forms. |
Closes #74
Initially the autocomplete feature is off until it is toggled with (autocomplete) but the window should save whether autocomplete was toggled so students won't have to keep enabling/disabling it.
The way I intended for this to work was for words to be displayed that the user could be typing. Once there is only one possible word left, the docs for that procedure is displayed. Also, for longer words, you can press tab to autocomplete the word that was being typed.
There are some things that can definitely be improved from this point. One thing is to maybe make the matching more sophisticated (right now I only match the prefixes of the word that is being typed with the possible words that can be displayed). Another thing is for something like define to not have the autocomplete box disappear when typing the function name and arguments.