Last active
February 26, 2021 11:25
-
-
Save unarist/a184bf5d936c82bed14007a56e8abfae to your computer and use it in GitHub Desktop.
This file contains hidden or 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
// ==UserScript== | |
// @name github - indent lines | |
// @namespace https://github.com/unarist/ | |
// @version 0.1 | |
// @description Tab/Shift+Tabでカーソル位置・選択行をインデント・アンインデント | |
// @author unarist | |
// @match https://github.com/* | |
// @grant none | |
// @downloadURL https://gist.github.com/unarist/a184bf5d936c82bed14007a56e8abfae/raw/github-indent-lines.user.js | |
// @run-at document-idle | |
// @noframes | |
// ==/UserScript== | |
/* | |
Tabが押されたらその行のインデントを深くする | |
Shift+Tabが押されたらインデントを浅くする | |
カーソル位置直前が /\* $/ /\* \[ \] $/ の場合に限定する? | |
keydownでpreventDefaultするとフォーカス移動は抑制できる | |
範囲選択してTab/Shift+TabはGithubが既に対応していた。が、execCommand使ってないのかUndo対応してない様子。 | |
これを置き換えるために capture: 1 使ってしまった。。 | |
*/ | |
(function() { | |
'use strict'; | |
const applyIndent = (el, unindent) => { | |
const linesStart = el.value.slice(0, el.selectionStart).lastIndexOf('\n') + 1; | |
const linesEnd = (() => { | |
const offset = el.value.slice(el.selectionEnd).indexOf('\n'); | |
if (offset < 0) return el.value.length; | |
else return el.selectionEnd + offset; | |
})(); | |
const prevLines = linesStart > 0 ? el.value.slice(0, linesStart - 1) : ""; | |
const selectedLines = el.value.slice(linesStart, linesEnd); | |
const nextLines = el.value.slice(linesEnd + 1); | |
const modifiedSelectedLines = selectedLines.split('\n').map(x => unindent ? x.replace(/^ /, '') : ' ' + x).join('\n'); | |
// unindentできないとずれるはず | |
const calcOffset = pos => pos <= linesStart ? 0 : selectedLines.slice(0, pos - linesStart).split('\n').length * (unindent ? -2 : 2); | |
const prevRange = [el.selectionStart, el.selectionEnd, el.selectionDirection]; | |
// Undo可能にするために、value更新ではなくexecCommandを使っている | |
el.setSelectionRange(linesStart, linesEnd); | |
document.execCommand('insertText', false, modifiedSelectedLines); | |
el.setSelectionRange(prevRange[0] + calcOffset(prevRange[0]), prevRange[1] + calcOffset(prevRange[1]), prevRange[2]); | |
//el.value = [prevLines, modifiedSelectedLines, nextLines].join('\n'); | |
}; | |
window.addEventListener('keydown', e => { | |
if (e.code === 'Tab' && e.target.matches('textarea')) { | |
e.preventDefault(); | |
e.stopPropagation(); | |
applyIndent(e.target, e.shiftKey); | |
} | |
}, { capture: true }); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment