Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CodeMirror custom hint list not working properly

I am trying to hook on CodeMirror and plug my own list of words to appear into the autocompletion. Based on this link https://stackoverflow.com/a/19269913/2892746 I tried to implement the following. I created a JSBin with it

The problem is that while my words do appear in the autocomplete, they are not filtered correctly. For example, I type "f", and then I do ctrl+space. But I get all the 3 words in the popup with "mariano" selected. I would expect to have only "Florencia" available and selected.

Any ideas what I could be doing wrong?

ps: yes, I would love to not change anyword hint and provide my own that simply matches my own words, but I don't know how to do that.

Thanks in advance!!

like image 530
Mariano Martinez Peck Avatar asked Apr 15 '16 16:04

Mariano Martinez Peck


2 Answers

I have finally solved this myself. I am not a JS expert, but I share my solution in case it is useful for someone else.

IMPORTANT: I got the original code from this project. That project was with Angular and Angular-codemirror dependency. I was not using Angular anywhere in my app so I extracted and adjusted it to use it without Angular.

The goal is to be able to define a dictionary/map of words that will be used for the autocomplete. The solution is very simple. At a parent of myTextAreaId element you must create a span/div like this:

 <div class="codeMirrorDictionaryHintDiv" codemirror-dictionary-hint="[ 'Soccer', 'Cricket', 'Baseball', 'Kho Kho' ]"></div>

Then...the code, will lookup the closest element with css class codeMirrorDictionaryHintDiv, will extract the attribute codemirror-dictionary-hint, will evaluate that in order to get a Javascript array out of it, and then simply set that as the input dictionary for the hint function.

The code is:

var dictionary = [];

try {
    // JSON.parse fails loudly, requiring a try-catch to prevent error propagation
    var dictionary = JSON.parse(
        document.getElementById('myTextAreaId')
         .closest('.codeMirrorDictionaryHintDiv')
          .getAttribute('codemirror-dictionary-hint')
    ) || []; 
} catch(e) {}


// Register our custom Codemirror hint plugin.
CodeMirror.registerHelper('hint', 'dictionaryHint', function(editor) {
    var cur = editor.getCursor();
    var curLine = editor.getLine(cur.line);
    var start = cur.ch;
    var end = start;
    while (end < curLine.length && /[\w$]/.test(curLine.charAt(end))) ++end;
    while (start && /[\w$]/.test(curLine.charAt(start - 1))) --start;
    var curWord = start !== end && curLine.slice(start, end);
    var regex = new RegExp('^' + curWord, 'i');
    return {
        list: (!curWord ? [] : dictionary.filter(function(item) {
            return item.match(regex);
        })).sort(),
        from: CodeMirror.Pos(cur.line, start),
        to: CodeMirror.Pos(cur.line, end)
    }
});

CodeMirror.commands.autocomplete = function(cm) {
    CodeMirror.showHint(cm, CodeMirror.hint.dictionaryHint);
};
like image 73
Mariano Martinez Peck Avatar answered Nov 10 '22 00:11

Mariano Martinez Peck


It's Happened When JS and Css Hint Files not Loaded! for the resolve it you must import them into your app manually :

1- Import Js File In Your TypeScript File:

//CodeMirror
import 'codemirror/addon/hint/sql-hint';
import 'codemirror/addon/hint/show-hint';

2- Import Css File Into Your Css App File

//CodeMirror
@import "~codemirror/addon/hint/show-hint.css";

GoodLuck

like image 38
HamidReza Heydari Avatar answered Nov 09 '22 22:11

HamidReza Heydari