Пользовательский список автозаполнения CodeMirror

У меня есть некоторые трудности с функцией автозаполнения в зеркале кода. То, что я пытаюсь сделать, это две вещи (с которыми я борюсь):

1) Я хочу включить автозаполнение для HTML и JavaScript. В настоящее время я могу получить только одну работу за раз, например:

 CodeMirror.commands.autocomplete = function (cm) {
     CodeMirror.showHint(cm, CodeMirror.hint.html);
 };

Как я могу добавить CodeMirror.hint.javascript в список из HTML?

2) (Что более важно) -- Как я могу добавить пользовательские переменные в список подсказок из HTML, какая область получена из вызова ajax.....

т. е. я хочу, чтобы раскрывающийся список отображался с текущим списком данных из подсказок html, но затем добавляю пользовательские записи, такие как ##SomeCode1## и ##SomeCode2##

У меня есть две проблемы. Сначала, когда я пытаюсь жестко закодировать значения в файле 'html-hint.js', все значения добавляются с помощью <..., чего я не хочу.

Вторая проблема заключается в том, что я считаю, что должен правильно написать новый файл html-hint.js? Я имею в виду, что нет никакого способа передать что-либо в параметре «options» в CodeMirror.hint.html выше, чтобы по существу объединить два списка.

Если подумать, я гость один и два - это одно и то же... Объединение двух списков значений для автозаполнения вместе.

Я предполагаю, что в фреймворке уже ничего нет, и мне нужно написать собственный файл подсказок, верно?

Любые указатели будут оценены. Пример кода был бы потрясающим.


person Robin Rieger    schedule 08.10.2013    source источник


Ответы (3)


Если вы не укажете функцию подсказки, аддон show-hint примет вспомогательную функцию подсказки, определенную для режима local, в котором происходит завершение, так что это будет CodeMirror.hint.javascript в коде JavaScript и CodeMirror.hint.html в коде. HTML.

Если вам нужно добавить свою собственную логику завершения, вы можете заменить (или обернуть) эти функции, просто перезаписав их своим собственным кодом.

Вот грубый пример хака, который всегда добавляет «bozo» к завершениям JavaScript:

var orig = CodeMirror.hint.javascript;
CodeMirror.hint.javascript = function(cm) {
  var inner = orig(cm) || {from: cm.getCursor(), to: cm.getCursor(), list: []};
  inner.list.push("bozo");
  return inner;
};
person Marijn    schedule 09.10.2013
comment
Очень полезно. Может быть, вы можете расширить свой ответ, как сделать настоящее автозаполнение, например, когда я вхожу в bo, будет предлагаться только bozo, а не f.e. foobar и что он не добавляет bozo после bo, а заменяет bo на bozo. Спасибо :) - person MonkeyMonkey; 29.01.2014
comment
Марин, приведенный выше код не работает должным образом. Слово "bozo" действительно добавлено в список, но когда я набираю "b-o-z...", оно не выделяется. Наоборот, если на моей странице есть функция с именем «обезьяна», когда я набираю «м-о-н...», это имя действительно выбирается. Кроме того, слово «бозо» отображается всегда, а не только тогда, когда пользователь вводит похожее слово. Это не ожидаемое поведение для автозаполнения. Есть ли другие способы сделать это? - person shmim; 20.05.2016
comment
Функция подсказки отвечает за фильтрацию. Если он просто безоговорочно добавляет слово, как в моем примере, никакой фильтрации не происходит. Но вы можете добавить туда свою логику, если хотите. - person Marijn; 21.05.2016

Спасибо @Marjin за краткое объяснение, но поскольку оно не распространяется на фильтрацию, а она нужна многим, вот что я сделал в mongoclient, следуя ответу Марджина. И частично воспользовался помощью здесь

p.s. Не забудьте заменить подсказку на свою, так как я использую javascript, я изменил подсказку javascript.

CodeMirror.hint.javascript = function (editor) {
        var list = Session.get(Template.strSessionDistinctFields) || [];
        var cursor = editor.getCursor();
        var currentLine = editor.getLine(cursor.line);
        var start = cursor.ch;
        var end = start;
        while (end < currentLine.length && /[\w$]+/.test(currentLine.charAt(end))) ++end;
        while (start && /[\w$]+/.test(currentLine.charAt(start - 1))) --start;
        var curWord = start != end && currentLine.slice(start, end);
        var regex = new RegExp('^' + curWord, 'i');
        var result = {
            list: (!curWord ? list : list.filter(function (item) {
                return item.match(regex);
            })).sort(),
            from: CodeMirror.Pos(cursor.line, start),
            to: CodeMirror.Pos(cursor.line, end)
        };

        return result;
    };
person Sercan Ozdemir    schedule 11.10.2016
comment
Можно ли добавить собственный список подсказок только к определенному экземпляру CodeMirror? - person peterremec; 05.12.2016
comment
ofc, в этом случае вам нужно создать свой собственный режим для codemirror, stackoverflow.com/questions/24433552/ - person Sercan Ozdemir; 05.12.2016
comment
Я не уверен, что мы понимаем друг друга. У меня есть два экземпляра режима SQL CodeMirror на странице с включенной функцией автозаполнения. Мне нужно добавить некоторые пользовательские ключевые слова в дополнение к встроенным ключевым словам sql. Я не понимаю, зачем мне создавать новый режим. Кроме того, я ищу способ динамически добавлять/удалять ключевые слова из этого списка. - person peterremec; 05.12.2016
comment
О, я вижу, к сожалению, я не так хорош в этом, может быть, вы можете создать новый вопрос, и люди смогут ответить, если у вас есть возможность пообщаться, найдите @Marjin, который является создателем codemirror. - person Sercan Ozdemir; 05.12.2016
comment
@SercanOzdemir Скажите, пожалуйста, как искать специальный символ в автозаполнении. я добавил подсказку по настройке, которая начинается с @, но в автозаполнении они не ищут с @ Пожалуйста, предложите.. var regex = new RegExp('^' + curWord, 'i'); Я думаю, что это регулярное выражение заменит. - person ; 17.10.2017
comment
@Goku, на самом деле вы уже ответили на свой вопрос, вам нужно экранировать специальные символы в конструкторе RegExp, чтобы он работал. - person Sercan Ozdemir; 17.10.2017
comment
@SercanOzdemir Я не знаю о регулярном выражении, которое я пробовал со своей стороны, но оно не дает правильного автозаполнения и не находит квадратную скобку. var регулярное выражение = curWord == [ ? регулярное выражение = новое регулярное выражение (\[.*?\], g) : регулярное выражение = новое регулярное выражение ('[@, ]*' + curWord, 'i'); Я пробовал это, но это не сработало - person ; 17.10.2017
comment
Я тоже, вам нужно посмотреть здесь: regular-expressions.info/characters.html - person Sercan Ozdemir; 17.10.2017
comment
Пожалуйста, предложите. Не нашел решения для следующей подсказки @input [ Square_Bracket ] - person ; 17.10.2017
comment
нет, вам нужно экранировать для каждого специального символа, когда они поступают из пользовательского ввода, например, для знака @ вам нужно написать его как \@, прежде чем вводить в конструктор RegExp - person Sercan Ozdemir; 17.10.2017
comment
Давайте продолжим обсуждение в чате. - person ; 17.10.2017
comment
Большое спасибо @SercanOzdemir, я пытался понять это целый день. - person Tarounen; 17.11.2019

Если это кому-то поможет, вот версия, которая сочетает в себе части как @Marjin, так и Sercan. Он использует подсказки по умолчанию и добавляет наши дополнения.

const hintWords=["trap.our()", "trap.hints()", "trap"]; // custom hints
const jsHinter = CodeMirror.hint.javascript; // copy default hinter for JavaScript
CodeMirror.hint.javascript = function (editor) {
    // Find the word fragment near cursor that needs auto-complete...
    const cursor = editor.getCursor();
    const currentLine = editor.getLine(cursor.line);
    let start = cursor.ch;
    let end = start;
    const rex=/[\w.]/; // a pattern to match any characters in our hint "words"
    // Our hints include function calls, e.g. "trap.getSource()"
    // so we search for word charcters (\w) and periods.
    // First (and optional), find end of current "word" at cursor...
    while (end < currentLine.length && rex.test(currentLine.charAt(end))) ++end;
    // Find beginning of current "word" at cursor...
    while (start && rex.test(currentLine.charAt(start - 1))) --start;
    // Grab the current word, if any...
    const curWord = start !== end && currentLine.slice(start, end);
    // Get the default results object from the JavaScript hinter...
    const dflt=jsHinter(editor);
    // If the default hinter didn't hint, create a blank result for now...
    const result = dflt || {list: []};
    // Set the start/end of the replacement range...
    result.to=CodeMirror.Pos(cursor.line, end);
    result.from=CodeMirror.Pos(cursor.line, start);
    // Add our custom hintWords to the list, if they start with the curWord...
    hintWords.forEach(h=>{if (h.startsWith(curWord)) result.list.push(h);});
    result.list.sort(); // sort the final list of hints
    return result;
};
person Chris Janicki    schedule 12.03.2021