-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial interactive fuzzy-search mode
- Loading branch information
Showing
6 changed files
with
234 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
const Input = require('../interactive/input'); | ||
const logUpdate = require('log-update'); | ||
const sortBySimilarity = require('../interactive/sort-by-similarity'); | ||
const getAction = require('./get'); | ||
const chalk = require('chalk'); | ||
const figures = require('figures'); | ||
|
||
module.exports = workspace => { | ||
let results = []; | ||
let currentResult = 0; | ||
let currentInputValue = ''; | ||
|
||
const modulesNames = workspace.getModulesNames(); | ||
|
||
const renderResults = () => { | ||
return results | ||
.map((result, i) => { | ||
if (i === results.length - currentResult - 1) { | ||
return `${chalk.red(figures.pointer)} ${chalk.bold( | ||
result.highlight, | ||
)}`; | ||
} | ||
return ` ${result.highlight}`; | ||
}) | ||
.join('\n'); | ||
}; | ||
|
||
const renderInputValue = () => { | ||
return `${chalk.cyan(figures.pointer)} ${currentInputValue}`; | ||
}; | ||
|
||
const renderAmountOfResults = () => { | ||
return chalk.dim.yellow(`${results.length}/${modulesNames.length}`); | ||
}; | ||
|
||
const renderUi = () => { | ||
logUpdate( | ||
`${renderResults()}\n${renderAmountOfResults()}\n${renderInputValue()}`, | ||
); | ||
}; | ||
|
||
results = sortBySimilarity(modulesNames, ''); | ||
renderUi(); | ||
|
||
const input = new Input({ | ||
stdin: process.stdin, | ||
}); | ||
|
||
input.on('change', obj => { | ||
currentInputValue = obj.valueWithCursor; | ||
results = sortBySimilarity(modulesNames, obj.value); | ||
renderUi(); | ||
}); | ||
|
||
input.on('up', () => { | ||
if (currentResult < results.length - 1) { | ||
currentResult++; | ||
} | ||
renderUi(); | ||
}); | ||
|
||
input.on('down', () => { | ||
if (currentResult > 0) { | ||
currentResult--; | ||
} | ||
renderUi(); | ||
}); | ||
|
||
input.on('choose', () => { | ||
if (results.length === 0) { | ||
return; | ||
} | ||
input.end(); | ||
logUpdate(''); | ||
const chosen = results[results.length - 1 - currentResult].value; | ||
console.log(getAction(workspace, chosen)); | ||
process.exit(0); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
const EventEmitter = require('events'); | ||
const chalk = require('chalk'); | ||
const { | ||
ctrlC, | ||
ctrlD, | ||
esc, | ||
left, | ||
right, | ||
up, | ||
down, | ||
enter, | ||
del, | ||
backspace, | ||
} = require('./raw-key-codes'); | ||
|
||
module.exports = class Input extends EventEmitter { | ||
constructor({ stdin }) { | ||
super(); | ||
|
||
this._value = []; | ||
this.cursorPos = 0; | ||
|
||
stdin.setRawMode(true); | ||
stdin.setEncoding('utf8'); | ||
|
||
stdin.on('error', e => { | ||
this.end(); | ||
console.error(e); | ||
}); | ||
|
||
stdin.on('data', this.onKeyPress.bind(this)); | ||
} | ||
|
||
get value() { | ||
return this._value.join(''); | ||
} | ||
|
||
get valueWithCursor() { | ||
if (this.cursorPos === this.value.length) { | ||
return this.value + chalk.inverse(' '); | ||
} | ||
|
||
const firstChunk = this.value.slice(0, this.cursorPos); | ||
const corsurChar = this.value.slice(this.cursorPos, this.cursorPos + 1); | ||
const secondChunk = this.value.slice(this.cursorPos + 1); | ||
|
||
return firstChunk + chalk.inverse(corsurChar) + secondChunk; | ||
} | ||
|
||
onKeyPress(key) { | ||
let changed = false; | ||
|
||
switch (key) { | ||
case ctrlC: | ||
case ctrlD: | ||
case esc: | ||
process.emit('SIGINT'); | ||
process.exit(1); | ||
break; | ||
case left: | ||
this.cursorPos = Math.max(0, this.cursorPos - 1); | ||
changed = true; | ||
break; | ||
case right: | ||
this.cursorPos = Math.min(this._value.length, this.cursorPos + 1); | ||
changed = true; | ||
break; | ||
case backspace: | ||
if (this.cursorPos !== 0) { | ||
this._value.splice(this.cursorPos - 1, 1); | ||
this.cursorPos = Math.max(0, this.cursorPos - 1); | ||
changed = true; | ||
} | ||
break; | ||
case del: | ||
if (this._value.length > this.cursorPos) { | ||
this._value.splice(this.cursorPos, 1); | ||
changed = true; | ||
} | ||
break; | ||
case up: | ||
this.emit('up'); | ||
break; | ||
case down: | ||
this.emit('down'); | ||
break; | ||
case enter: | ||
this.emit('choose'); | ||
break; | ||
default: | ||
this.insertChar(key); | ||
changed = true; | ||
} | ||
|
||
if (changed) { | ||
this.emit('change', this); | ||
} | ||
} | ||
|
||
insertChar(char) { | ||
this._value.splice(this.cursorPos, 0, char); | ||
this.cursorPos++; | ||
} | ||
|
||
end() { | ||
this.removeAllListeners(); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module.exports.ctrlC = '\u0003'; | ||
module.exports.ctrlD = '\u0004'; | ||
module.exports.esc = '\u001b'; | ||
module.exports.left = '\u001b\u005b\u0044'; | ||
module.exports.right = '\u001b\u005b\u0043'; | ||
module.exports.up = '\u001b\u005b\u0041'; | ||
module.exports.down = '\u001b\u005b\u0042'; | ||
module.exports.enter = '\u000d'; | ||
module.exports.del = '\u001b\u005b\u0033\u007e'; | ||
module.exports.backspace = '\u007f'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
const fuzzysort = require('fuzzysort'); | ||
|
||
module.exports = (list, string) => { | ||
return fuzzysort | ||
.go(string, list, { | ||
threshold: -20, // Don't return matches worse than this (higher is faster) | ||
limit: Infinity, // Don't return more results than this (lower is faster) | ||
allowTypo: true, // Allwos a snigle transpoes (false is faster) | ||
}) | ||
.sort((a, b) => a.score > b.score) | ||
.map(result => { | ||
return { | ||
value: result.target, | ||
score: result.score, | ||
highlight: fuzzysort.highlight(result, '\u001b[32m', '\u001b[39m') // eslint-disable-line | ||
}; | ||
}); | ||
}; |