Skip to content

Instantly share code, notes, and snippets.

@nexpr
Created June 14, 2017 14:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nexpr/047df162c456082c36ca236cb0a4490f to your computer and use it in GitHub Desktop.
Save nexpr/047df162c456082c36ca236cb0a4490f to your computer and use it in GitHub Desktop.
Command tool like snipet.
const snip_start_marker = "@"
const snip_end_marker = ";"
const accept_sources = [
"textarea", "input[type=text]"
]
const snimap = {
"test": "てすと",
"run"(elem){
console.log(elem)
},
"tabindent"(elem){
const pre = elem.value
elem.value = pre.replace(/^ {4,}/g, e =>
"\t".repeat(~~(e.length / 4)) + " ".repeat(e.length % 4))
if(elem.value !== pre){
elem.selectionStart = elem.selectionEnd = elem.value.length
}
},
"doctype"(elem){
const text = `<!doctype html>\n<meta charset="utf-8">\n`
elem.value = strinsert(elem.value, elem.selectionStart, text)
setCaret(elem, elem.selectionStart + text.length)
},
"expand"(elem){
let start
{
let i = elem.selectionStart
while(true){
const char = elem.value.charAt(--i)
if(char === "\n" || char === ""){
start = i + 1
break
}
}
}
const snivar = elem.value.slice(start, elem.selectionStart)
const matched = snivar.trim().match(/^(-?\d+) *\: *(-?\d+)$/)
if(!matched) return
const rstart = ~~matched[1]
const rend = ~~matched[2]
if(rstart > rend) return
const text = Array.from(Array(rend - rstart + 1), (e, i) => rstart + i).join("\n")
replaceElementText(elem, text, start, elem.selectionStart)
}
}
function strcut(str, start, end){
return str.substr(0, start) + str.substr(end)
}
function strinsert(str, index, text){
return str.substr(0, index) + text + str.substr(index)
}
function setCaret(elem, start, end = start){
elem.selectionStart = start
elem.selectionEnd = end
}
function replaceElementText(elem, text, start, end = start){
const inipos = elem.selectionStart
elem.value = strinsert(strcut(elem.value, start, end), start, text)
if(inipos >= start){
const newpos = start + text.length
setCaret(elem, newpos)
}
}
function checkSnip(elem){
if(!(elem.selectionStart === elem.selectionEnd && elem.selectionStart)){
return false
}
const end = elem.selectionStart
let start
{
let i = elem.selectionStart
while(true){
const char = elem.value.charAt(--i)
if(char === "\n" || char === ""){
return false
}
if(char === snip_start_marker){
start = i
break
}
}
}
const snip = elem.value.slice(start + 1, end)
if(!(snip in snimap)){
return false
}
return {start, end, key: snip}
}
window.addEventListener("keydown", eve => {
const elem = eve.target
const do_handle = accept_sources.some(e => eve.target.matches(e))
&& eve.key === snip_end_marker
if(!do_handle) return
const snip = checkSnip(elem)
if(!snip) return
const action = snimap[snip.key]
elem.value = strcut(elem.value, snip.start, snip.end)
setCaret(elem, snip.start)
if(typeof action === "string"){
elem.value = strinsert(elem.value, snip.start, action)
setCaret(elem, snip.start + action.length)
}else{
action(elem)
}
eve.preventDefault()
eve.stopPropagation()
}, true)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment