Skip to content

Instantly share code, notes, and snippets.

View andy0130tw's full-sized avatar
🍌
why no 🍆

Andy Pan andy0130tw

🍌
why no 🍆
View GitHub Profile
@andy0130tw
andy0130tw / cm-draggable-gutter.js
Last active October 1, 2024 18:39
Draggable gutter for selecting lines
import {
StateField,
StateEffect,
EditorSelection,
StateEffectType,
} from '@codemirror/state'
import { EditorView, ViewPlugin } from '@codemirror/view'
/** @import { Text, Line } from '@codemirror/state' */
/** @import { PluginValue, BlockInfo } from '@codemirror/view' */
@andy0130tw
andy0130tw / cm-single-line.js
Last active October 1, 2024 18:21
Sample single line setup CodeMirror; note that you need to tweak the default keymap
import { minimalSetup } from 'codemirror'
import { EditorState } from '@codemirror/state'
import { EditorView, keymap } from '@codemirror/view'
import { insertNewlineAndIndent, insertBlankLine } from '@codemirror/commands'
function removeNewlineCommands(exts) {
const newlineCommands = [insertNewlineAndIndent, insertBlankLine]
return exts.map(ext => {
if (ext?.facet == keymap) {
@andy0130tw
andy0130tw / cm-enhanced-search-field.js
Last active October 8, 2024 07:02
CodeMirror with a search field that is another CodeMirror instance!
import { basicSetup, minimalSetup } from 'codemirror'
import { Prec } from '@codemirror/state'
import { EditorView, keymap, placeholder } from '@codemirror/view'
import { search, findNext, findPrevious } from '@codemirror/search'
const SearchPanel = (() => {
const searchConfigFacet = search({})[0].facet
@andy0130tw
andy0130tw / jd.grammar
Created September 10, 2024 19:10
Lezer grammar definition for JSON diff syntax used by jd (https://github.com/josephburnett/jd). Built on top of JSON's grammar.
@top JSONDiff { section* }
value { True | False | Null | Number | String | Object | Array }
section {
Header
(Deletion+ Insertion* | Insertion+)
}
Header { "@" "[" list<path> "]" "\n" }
@andy0130tw
andy0130tw / cm-candidate-selector-demo.js
Last active September 9, 2024 19:07
Sample integration of input method "agda-input" for CodeMirror
import {basicSetup} from 'codemirror'
import {
autocompletion,
completionStatus,
setSelectedCompletion,
currentCompletions,
selectedCompletionIndex,
moveCompletionSelection,
closeBrackets,
} from '@codemirror/autocomplete'
@andy0130tw
andy0130tw / JavaScript.sublime-settings
Created August 21, 2024 06:54
Fix JSDoc autocompletion in JavaScript in Sublime Text
// These settings override both User and Default settings for the JavaScript syntax
{
"auto_complete_selector": "meta.tag, comment.block.documentation, source - comment - string.quoted.double.block - string.quoted.single.block - string.unquoted.heredoc",
}
import { foldService } from '@codemirror/language'
/** @param {string} text */
function indentLevel(text) {
const mat = /** @type {RegExpMatchArray} */ (
text.match(/^( *)([^ ]?)/))
return mat[2] ? mat[1].length : -1
}
export const foldByIndentation = foldService.of(({ doc }, from, _to) => {
@andy0130tw
andy0130tw / my-codemirror-state-fuzzer.js
Last active August 3, 2024 19:05
I cannot write something reliable so I write a fuzzer first ε(´。•᎑•`)っ 💕
import { EditorState, Text } from '@codemirror/state'
import { changeTracker, lineStatistics, commit } from './lib/codemirror/experiments.js'
/** @typedef {{ len: number, count: number }} LineStat */
function countSurrogates(/** @type {string} */ s) {
const regex = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g
let n = 0
while (regex.exec(s)) n++
return n
@andy0130tw
andy0130tw / agda-stdout-reader.js
Last active July 26, 2024 18:18
Read stdout from Agda's interaction mode (JSON/Emacs)
/** Given chunks as iov, truncate the prompt if possible.
* @param {string[]} chunks
* @param {string} prompt
*/
function truncatePrompt(chunks, prompt) {
/** Does the iov start with the given prefix? Return the end position [x, y] if yes, null if no.
* @param {string[]} chunks
* @param {string} target
*/
function chunksStartWithPrefix(chunks, target) {
@andy0130tw
andy0130tw / reducer-with-generator.js
Created July 24, 2024 19:23
Did I abuse generators 🫠
function byCallbacks(s0, inp) {
if (inp == null) {
let s = s0
if (s0.integerPart === '') {
s = { ...s0, integerPart: '0' }
}
return s.integerPart + (s.decimalPart ? `.${s.decimalPart}` : '')
} if (s0.readingIntegerPart) {
if (inp === '.') {