diff options
| author | Hsieh Chin Fan <pham@topo.tw> | 2024-09-13 18:52:45 +0800 |
|---|---|---|
| committer | Hsieh Chin Fan <pham@topo.tw> | 2024-09-13 18:59:14 +0800 |
| commit | e8a94e5e43a306753b99615554e76a0815df090e (patch) | |
| tree | 31941c5c69541225b14734a17084ed06cd3d76a7 /src | |
| parent | f1f5462fadd410dbbb6c284481b6ca7219313e64 (diff) | |
fix: Logic about suggestions
* Switch to event 'onCursorActivity' for suggestions
* Show suggestion about Renderer without case sensitive
Diffstat (limited to 'src')
| -rw-r--r-- | src/editor.mjs | 59 |
1 files changed, 35 insertions, 24 deletions
diff --git a/src/editor.mjs b/src/editor.mjs index d1b4ba1..bf59e47 100644 --- a/src/editor.mjs +++ b/src/editor.mjs | |||
| @@ -166,21 +166,24 @@ fetch(defaultApply) | |||
| 166 | // return true | 166 | // return true |
| 167 | // } | 167 | // } |
| 168 | // }}} | 168 | // }}} |
| 169 | // FUNCTION Check if current token is inside code block {{{ | 169 | // FUNCTION: Check if current token is inside code block {{{ |
| 170 | const insideCodeblockForMap = (token) => | 170 | const insideCodeblockForMap = (anchor) => { |
| 171 | token.state.overlay.codeBlock && !token.string.match(/^````*/) | 171 | const token = cm.getTokenAt(anchor) |
| 172 | const result = token.state.overlay.codeBlock && !cm.getLine(anchor.line).match(/^````*/) | ||
| 173 | return result | ||
| 174 | } | ||
| 172 | // }}} | 175 | // }}} |
| 173 | // FUNCTION: Get renderer by cursor position in code block {{{ | 176 | // FUNCTION: Get renderer by cursor position in code block {{{ |
| 174 | const getLineWithRenderer = (anchor) => { | 177 | const getLineWithRenderer = (anchor) => { |
| 175 | const currentLine = anchor.line | 178 | const currentLine = anchor.line |
| 176 | const match = (line) => cm.getLine(line).match(/^use: /) | 179 | const match = (line) => cm.getLine(line).match(/^use: /) |
| 180 | |||
| 177 | if (match(currentLine)) return currentLine | 181 | if (match(currentLine)) return currentLine |
| 178 | 182 | ||
| 179 | const getToken = (line) => cm.getTokenAt({ line: line, ch: 1 }) | ||
| 180 | 183 | ||
| 181 | // Look backward/forward for pattern of used renderer: /use: .+/ | 184 | // Look backward/forward for pattern of used renderer: /use: .+/ |
| 182 | let ps = currentLine - 1 | 185 | let ps = currentLine - 1 |
| 183 | while (ps > 0 && insideCodeblockForMap(getToken(ps))) { | 186 | while (ps > 0 && insideCodeblockForMap(anchor)) { |
| 184 | if (match(ps)) { | 187 | if (match(ps)) { |
| 185 | return ps | 188 | return ps |
| 186 | } else if (cm.getLine(ps).match(/^---/)) { | 189 | } else if (cm.getLine(ps).match(/^---/)) { |
| @@ -191,11 +194,10 @@ const getLineWithRenderer = (anchor) => { | |||
| 191 | } | 194 | } |
| 192 | 195 | ||
| 193 | let ns = currentLine + 1 | 196 | let ns = currentLine + 1 |
| 194 | while (insideCodeblockForMap(getToken(ns))) { | 197 | while (insideCodeblockForMap(anchor)) { |
| 195 | if (match(ns)) { | 198 | if (match(ns)) { |
| 196 | return ns | 199 | return ns |
| 197 | } else if (cm.getLine(ns).match(/^---/)) { | 200 | } else if (cm.getLine(ns).match(/^---/)) { |
| 198 | // If yaml doc separator is found | ||
| 199 | return null | 201 | return null |
| 200 | } | 202 | } |
| 201 | ns = ns + 1 | 203 | ns = ns + 1 |
| @@ -265,18 +267,22 @@ const handleTypingInCodeBlock = (anchor) => { | |||
| 265 | // }}} | 267 | // }}} |
| 266 | // FUNCTION: get suggestions by current input {{{ | 268 | // FUNCTION: get suggestions by current input {{{ |
| 267 | const getSuggestions = (anchor) => { | 269 | const getSuggestions = (anchor) => { |
| 268 | const text = cm.getLine(anchor.line) | ||
| 269 | const markInputIsInvalid = () => cm.getDoc().markText( | ||
| 270 | { ...anchor, ch: 0 }, | ||
| 271 | { ...anchor, ch: -1 }, | ||
| 272 | { className: 'invalid-input' }, | ||
| 273 | ) | ||
| 274 | let suggestions = [] | 270 | let suggestions = [] |
| 271 | const text = cm.getLine(anchor.line) | ||
| 272 | const markInputIsInvalid = () => { | ||
| 273 | cm.getDoc().markText( | ||
| 274 | { ...anchor, ch: 0 }, | ||
| 275 | { ...anchor, ch: -1 }, | ||
| 276 | { className: 'invalid-input' }, | ||
| 277 | ) | ||
| 278 | } | ||
| 275 | 279 | ||
| 276 | // Check if "use: <renderer>" is set | 280 | // Check if "use: <renderer>" is set |
| 277 | const lineWithRenderer = getLineWithRenderer(anchor) | 281 | const lineWithRenderer = getLineWithRenderer(anchor) |
| 278 | const renderer = cm.getLine(lineWithRenderer).split(' ')[1] | 282 | const renderer = lineWithRenderer |
| 279 | if (renderer) { | 283 | ? cm.getLine(lineWithRenderer).split(' ')[1] |
| 284 | : null | ||
| 285 | if (renderer && anchor.line !== lineWithRenderer) { | ||
| 280 | // Do not check properties | 286 | // Do not check properties |
| 281 | if (text.startsWith(' ')) return [] | 287 | if (text.startsWith(' ')) return [] |
| 282 | 288 | ||
| @@ -288,10 +294,14 @@ const getSuggestions = (anchor) => { | |||
| 288 | import(rendererUrl) | 294 | import(rendererUrl) |
| 289 | .then(rendererModule => { | 295 | .then(rendererModule => { |
| 290 | rendererOptions[renderer] = rendererModule.default.validOptions | 296 | rendererOptions[renderer] = rendererModule.default.validOptions |
| 297 | const currentAnchor = cm.getCursor() | ||
| 298 | if (insideCodeblockForMap(currentAnchor)) { | ||
| 299 | handleTypingInCodeBlock(currentAnchor) | ||
| 300 | } | ||
| 291 | }) | 301 | }) |
| 292 | .catch(_ => { | 302 | .catch(_ => { |
| 293 | markInputIsInvalid(lineWithRenderer) | 303 | markInputIsInvalid(lineWithRenderer) |
| 294 | console.warn(`Fail to get valid options from renderer with URL ${rendererUrl}`) | 304 | console.warn(`Fail to get valid options from Renderer typed: ${renderer}`) |
| 295 | }) | 305 | }) |
| 296 | return [] | 306 | return [] |
| 297 | } | 307 | } |
| @@ -336,10 +346,10 @@ const getSuggestions = (anchor) => { | |||
| 336 | const rendererSuggestions = Object.entries(defaultAliasesForRenderer.use) | 346 | const rendererSuggestions = Object.entries(defaultAliasesForRenderer.use) |
| 337 | .filter(([renderer,]) => { | 347 | .filter(([renderer,]) => { |
| 338 | const suggestion = `use: ${renderer}` | 348 | const suggestion = `use: ${renderer}` |
| 339 | const suggetionNoSpace = suggestion.replace(' ', '') | 349 | const suggestionPattern = suggestion.replace(' ', '').toLowerCase() |
| 340 | const textNoSpace = text.replace(' ', '') | 350 | const textPattern = text.replace(' ', '').toLowerCase() |
| 341 | return suggestion !== text && | 351 | return suggestion !== text && |
| 342 | (suggetionNoSpace.includes(textNoSpace)) | 352 | (suggestionPattern.includes(textPattern)) |
| 343 | }) | 353 | }) |
| 344 | .map(([renderer, info]) => | 354 | .map(([renderer, info]) => |
| 345 | new Suggestion({ | 355 | new Suggestion({ |
| @@ -392,15 +402,16 @@ const addSuggestions = (anchor, suggestions) => { | |||
| 392 | const rect = suggestionsEle.getBoundingClientRect() | 402 | const rect = suggestionsEle.getBoundingClientRect() |
| 393 | suggestionsEle.style.maxWidth = `calc(${window.innerWidth}px - ${rect.x}px - 2rem)`; | 403 | suggestionsEle.style.maxWidth = `calc(${window.innerWidth}px - ${rect.x}px - 2rem)`; |
| 394 | suggestionsEle.style.display = 'block' | 404 | suggestionsEle.style.display = 'block' |
| 405 | suggestionsEle.style.transform = 'translate(2em, 1em)' | ||
| 395 | } | 406 | } |
| 396 | // }}} | 407 | // }}} |
| 397 | // EVENT: suggests for current selection {{{ | 408 | // EVENT: Suggests for current selection {{{ |
| 398 | // FIXME Dont show suggestion when selecting multiple chars | 409 | // FIXME Dont show suggestion when selecting multiple chars |
| 399 | cm.on("beforeSelectionChange", (_, obj) => { | 410 | cm.on("cursorActivity", (_) => { |
| 400 | const anchor = (obj.ranges[0].anchor) | 411 | suggestionsEle.style.display = 'none' |
| 401 | const token = cm.getTokenAt(anchor) | 412 | const anchor = cm.getCursor() |
| 402 | 413 | ||
| 403 | if (insideCodeblockForMap(token)) { | 414 | if (insideCodeblockForMap(anchor)) { |
| 404 | handleTypingInCodeBlock(anchor) | 415 | handleTypingInCodeBlock(anchor) |
| 405 | } | 416 | } |
| 406 | }); | 417 | }); |