Download src/js/views/commandViews.js from merve/git-101: direct link, hf CLI and curl.
- Browser
- Download file 7.17 kB
-
https://huggingface.co/spaces/merve/git-101/resolve/main/src/js/views/commandViews.js
- Command line
-
hf download hf://spaces/merve/git-101/src/js/views/commandViews.js
-
curl -L -o commandViews.js https://huggingface.co/spaces/merve/git-101/resolve/main/src/js/views/commandViews.js
7.17 kB
| var Backbone = require('backbone'); | |
| const {getAllCommands} = require('../sandbox/commands'); | |
| var Main = require('../app'); | |
| var CommandLineStore = require('../stores/CommandLineStore'); | |
| var CommandLineActions = require('../actions/CommandLineActions'); | |
| var log = require('../log'); | |
| var keyboard = require('../util/keyboard'); | |
| const allCommands = Object.keys(getAllCommands()); | |
| // Lets push a few commands up in the suggestion order, | |
| // which overrides the order from the exportj | |
| const autoCompleteSuggestionOrder = [ | |
| 'levels', // above "level" | |
| 'help', // above help level since you might not be in a level | |
| 'show solution', // above show goal since you start with a goal view | |
| 'reset', // over reset solved | |
| 'import level', // over import tree | |
| ]; | |
| const allCommandsSorted = autoCompleteSuggestionOrder.concat( | |
| // add the rest that arent in the list above | |
| allCommands.map(command => autoCompleteSuggestionOrder.indexOf(command) > 0 ? null : command) | |
| .filter(command => !!command) | |
| ); | |
| var CommandPromptView = Backbone.View.extend({ | |
| initialize: function() { | |
| Main.getEvents().on('commandSubmittedPassive', this.addToCommandHistory, this); | |
| this.index = -1; | |
| this.commandParagraph = this.$('#prompt p.command')[0]; | |
| this.focus(); | |
| Main.getEvents().on('rollupCommands', this.rollupCommands, this); | |
| Main.getEventBaton().stealBaton('keydown', this.onKeyDown, this); | |
| Main.getEventBaton().stealBaton('keyup', this.onKeyUp, this); | |
| this.updatePrompt(" "); | |
| }, | |
| events: { | |
| 'blur #commandTextField': 'hideCursor', | |
| 'focus #commandTextField': 'showCursor' | |
| }, | |
| blur: function() { | |
| this.hideCursor(); | |
| }, | |
| focus: function() { | |
| this.$('#commandTextField').focus(); | |
| this.showCursor(); | |
| }, | |
| hideCursor: function() { | |
| this.toggleCursor(false); | |
| }, | |
| showCursor: function() { | |
| this.toggleCursor(true); | |
| }, | |
| toggleCursor: function(state) { | |
| $(this.commandParagraph).toggleClass('showCursor', state); | |
| }, | |
| onKeyDown: function(e) { | |
| var el = e.target; | |
| const shadowEl = document.querySelector('#shadow'); | |
| const currentValue = el.value; | |
| const allCommand = currentValue.split(';'); | |
| const lastCommand = allCommand[allCommand.length - 1] | |
| .replace(/\s\s+/g, ' ').replace(/^\s/, ''); | |
| shadowEl.innerHTML = ''; | |
| if (lastCommand.length) { | |
| for (const c of allCommandsSorted) { | |
| if (c.startsWith(lastCommand)) { | |
| shadowEl.innerHTML = (currentValue + c.replace(lastCommand, '')).replace(/ /g, ' '); | |
| break; | |
| } | |
| } | |
| } | |
| if (e.keyCode === 9) { | |
| e.preventDefault(); | |
| if (shadowEl.innerHTML) { | |
| el.value = shadowEl.innerHTML.replace(/ /g, ' '); | |
| } | |
| } | |
| this.updatePrompt(el); | |
| }, | |
| onKeyUp: function(e) { | |
| this.onKeyDown(e); | |
| // we need to capture some of these events. | |
| var keyToFuncMap = { | |
| enter: function() { | |
| this.submit(); | |
| }.bind(this), | |
| up: function() { | |
| this.commandSelectChange(1); | |
| }.bind(this), | |
| down: function() { | |
| this.commandSelectChange(-1); | |
| }.bind(this) | |
| }; | |
| var key = keyboard.mapKeycodeToKey(e.which || e.keyCode); | |
| if (keyToFuncMap[key] !== undefined) { | |
| e.preventDefault(); | |
| keyToFuncMap[key](); | |
| this.onKeyDown(e); | |
| } | |
| }, | |
| badHtmlEncode: function(text) { | |
| return text.replace(/&/g,'&') | |
| .replace(/</g,'<') | |
| .replace(/</g,'<') | |
| .replace(/ /g,' ') | |
| .replace(/\n/g,''); | |
| }, | |
| updatePrompt: function(el) { | |
| el = el || {}; // firefox | |
| // i WEEEPPPPPPpppppppppppp that this reflow takes so long. it adds this | |
| // super annoying delay to every keystroke... I have tried everything | |
| // to make this more performant. getting the srcElement from the event, | |
| // getting the value directly from the dom, etc etc. yet still, | |
| // there's a very annoying and sightly noticeable command delay. | |
| // try.github.com also has this, so I'm assuming those engineers gave up as | |
| // well... | |
| var text = $('#commandTextField').val(); | |
| // Alright so we have our initial value for what we want the | |
| // command line to contain. We need to next split into the | |
| // parse with the cursor and without | |
| var selectionStart = el.selectionStart; | |
| var selectionEnd = el.selectionEnd; | |
| if (!text.length) { | |
| text = ' '; | |
| selectionStart = 0; | |
| selectionEnd = 1; | |
| } else if (selectionStart === selectionEnd) { | |
| // Lets pretend they have selected the end character to make the cursor | |
| // shown | |
| text += ' '; | |
| selectionEnd += 1; | |
| } else if (selectionStart === undefined || selectionEnd === undefined) { | |
| // I donno what this is for | |
| selectionStart = Math.max(text.length - 1, 0); | |
| selectionEnd = text.length; | |
| } | |
| var before = text.substring(0, selectionStart); | |
| var middle = text.substring(selectionStart, selectionEnd); | |
| var end = text.substring(selectionEnd, text.length); | |
| // Then just make three spans and slap it in. | |
| var finalHTML = '<span>' + this.badHtmlEncode(before) + '</span>' + | |
| '<span class="commandCursor">' + this.badHtmlEncode(middle) + '</span>' + | |
| '<span>' + this.badHtmlEncode(end) + '</span>'; | |
| this.commandParagraph.innerHTML = finalHTML; | |
| // and scroll down due to some weird bug | |
| Main.getEvents().trigger('commandScrollDown'); | |
| }, | |
| commandSelectChange: function(delta) { | |
| this.index += delta; | |
| // if we are over / under, display blank line. yes this eliminates your | |
| // partially edited command, but i doubt that is much in this demo | |
| if (this.index >= CommandLineStore.getCommandHistoryLength() || this.index < 0) { | |
| this.clear(); | |
| this.index = -1; | |
| return; | |
| } | |
| // yay! we actually can display something | |
| var commandEntry = CommandLineStore.getCommandHistory()[this.index]; | |
| this.setTextField(commandEntry); | |
| }, | |
| setTextField: function(value) { | |
| this.$('#commandTextField').val(value); | |
| }, | |
| clear: function() { | |
| this.setTextField(''); | |
| }, | |
| submit: function() { | |
| var value = this.$('#commandTextField').val().replace('\n', ''); | |
| this.clear(); | |
| this.submitCommand(value); | |
| this.index = -1; | |
| }, | |
| rollupCommands: function(numBack) { | |
| var which = CommandLineStore.getCommandHistory().slice(1, Number(numBack) + 1); | |
| which.reverse(); | |
| var str = ''; | |
| which.forEach(function(text) { | |
| str += text + ';'; | |
| }, this); | |
| CommandLineActions.submitCommand(str); | |
| }, | |
| addToCommandHistory: function(value) { | |
| // we should add the command to our local storage history | |
| // if it's not a blank line and this is a new command... | |
| // or if we edited the command in place in history | |
| var shouldAdd = (value.length && this.index === -1) || | |
| ((value.length && this.index !== -1 && | |
| CommandLineStore.getCommandHistory()[this.index] !== value)); | |
| if (!shouldAdd) { | |
| return; | |
| } | |
| CommandLineActions.submitCommand(value); | |
| log.commandEntered(value); | |
| }, | |
| submitCommand: function(value) { | |
| Main.getEventBaton().trigger('commandSubmitted', value); | |
| } | |
| }); | |
| exports.CommandPromptView = CommandPromptView; | |