如何使用 codemirror 启用代码提示?
Posted
技术标签:
【中文标题】如何使用 codemirror 启用代码提示?【英文标题】:How to enable code hinting using codemirror? 【发布时间】:2015-11-16 21:44:08 【问题描述】:我正在使用 codemirror 来允许用户输入任何代码,例如 css/html/js。
如果用户在 css 模式下输入类似内容,我需要启用
div
padding-
它应该提示用户从列表中选择可用的选项,例如
div
padding-top
padding-left
padding-right
padding-bottom
类似于使用 codemirror 的 sublime 编辑器。 sublime 自动提示的演示请参见附图
这是我的代码:
<script src="codemirror-5.4/mode/javascript/javascript.js"></script>
<script src="codemirror-5.4/mode/css/css.js"></script>
<script src="codemirror-5.4/mode/htmlmixed/htmlmixed.js"></script>
<script src="codemirror-5.4/addon/display/fullscreen.js"></script>
<script src="codemirror-5.4/keymap/sublime.js"></script>
<script src="codemirror-5.4/addon/hint/show-hint.js"></script>
<script src="codemirror-5.4/addon/hint/css-hint.js"></script>
<script src="codemirror-5.4/addon/hint/javascript.js"></script>
<h3>Editor</h3>
<div class="control-group">
<label class="control-label" for="textarea2">HTML</label>
<div class="controls">
<textarea class="code" name="code" id="codert" cols="40" rows="5" placeholder="Enter code here ..." style="width: 810px; height: 200px">
</textarea>
</div>
</div>
<div class="control-group">
<label class="control-label" for="textarea3">CSS</label>
<div class="controls">
<textarea id="code" class="code" name="codeCSS" cols="40" rows="5" placeholder="Enter code here ..." style="width: 810px; height: 200px">
</textarea>
</div>
</div>
<div class="control-group">
<label class="control-label" for="textarea3">javascript</label>
<div class="controls">
<textarea id="codeJS" class="code" name="codeJS" cols="40" rows="5" placeholder="Enter code here ..." style="width: 0px; height: 0px">
</textarea>
</div>
</div>
codemirror 的 JavaScript 代码
<script>
function loadCSS()
var $head = $("#preview").contents().find("head");
$head.html("<style>" + editor.getValue() + "</style>");
;
function loadJS()
var scriptTag = "<script>"+editorJS.getValue()+"<";
scriptTag += "/script>";
var previewFrame2 = document.getElementById('preview');
var preview2 = previewFrame2.contentDocument || previewFrame2.contentWindow.document;
preview2.open();
preview2.write(editor2.getValue()+scriptTag);
preview2.close();
loadCSS();
;
var delay;
// Initialize CodeMirror editor with a nice html5 canvas demo.
// css editor
var editor = CodeMirror.fromTextArea(document.getElementById('code'),
lineNumbers: true,
styleActiveLine: true,
matchBrackets: true,
mode: "text/x-scss",
keyMap: "sublime",
theme: 'monokai',
autoCloseTags: true,
lineWrapping: true,
extraKeys: "Ctrl-Space": "autocomplete"
);
editor.on("change", function()
clearTimeout(delay);
delay = setTimeout(updatePreview, 0);
);
function updatePreview()
loadCSS();
setTimeout(updatePreview, 0);
var delay2;
// Initialize CodeMirror editor with a nice html5 canvas demo.
var editor2 = CodeMirror.fromTextArea(document.getElementById('codert'),
lineNumbers: true,
styleActiveLine: true,
matchBrackets: true,
mode: "text/html",
keyMap: "sublime",
theme: 'monokai',
autoCloseTags: true,
lineWrapping: true,
extraKeys: "Ctrl-Space": "autocomplete"
);
editor2.on("change", function()
clearTimeout(delay2);
delay2 = setTimeout(updatePreview2, 0);
);
function updatePreview2()
var scriptTag = "<script>"+editorJS.getValue()+"<";
scriptTag += "/script>";
var previewFrame2 = document.getElementById('preview');
var preview2 = previewFrame2.contentDocument || previewFrame2.contentWindow.document;
preview2.open();
preview2.write(editor2.getValue()+scriptTag);
preview2.close();
loadCSS();
setTimeout(updatePreview2, 0);
var delayJS;
// Initialize CodeMirror editor with a nice html5 canvas demo.
var editorJS = CodeMirror.fromTextArea(document.getElementById('codeJS'),
lineNumbers: true,
styleActiveLine: true,
matchBrackets: true,
mode: 'javascript',
keyMap: "sublime",
theme: 'monokai',
autoCloseTags: true,
lineWrapping: true,
extraKeys: "Ctrl-Space": "autocomplete"
);
editorJS.on("change", function()
clearTimeout(delayJS);
delayJS = setTimeout(updatePreviewJS, 0);
);
function updatePreviewJS()
loadJS();
setTimeout(updatePreviewJS, 0);
</script>
【问题讨论】:
【参考方案1】:来自code mirror website
function getCompletions(token, context)
var found = [], start = token.string;
function maybeAdd(str)
if (str.indexOf(start) == 0) found.push(str);
function gatherCompletions(obj)
if (typeof obj == "string") forEach(stringProps, maybeAdd);
else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
else if (obj instanceof Function) forEach(funcProps, maybeAdd);
for (var name in obj) maybeAdd(name);
if (context)
// If this is a property, see if it belongs to some object we can
// find in the current environment.
var obj = context.pop(), base;
if (obj.className == "js-variable")
base = window[obj.string];
else if (obj.className == "js-string")
base = "";
else if (obj.className == "js-atom")
base = 1;
while (base != null && context.length)
base = base[context.pop().string];
if (base != null) gatherCompletions(base);
else
// If not, just look in the window object and any local scope
// (reading into JS mode internals to get at the local variables)
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
gatherCompletions(window);
forEach(keywords, maybeAdd);
return found;
您按 ctrl+空格来启用代码提示。
【讨论】:
那是 javascript。 html函数可以在这里找到codemirror.net/demo/html5complete.html 你写的代码是codemirror提供的demo示例代码。但该功能不仅仅适用于该代码。顺便说一句,css自动提示怎么样?任何想法?谢谢! @Packer 我在回答中说它来自网站。对css一无所知。谷歌群组上有一个关于它的大讨论! 我认为这可能行得通***.com/a/19544473/1675954,有没有投票的机会?【参考方案2】:您没有发布所有代码,所以我可能是错的,但请确保将 show-hint.css
样式表添加到页眉。
<link rel="stylesheet" href="../addon/hint/show-hint.css">
否则,提示不会出现,我认为自动完成功能不起作用。
【讨论】:
【参考方案3】:编织:http://kodeweave.sourceforge.net/editor/#bc08cb08dee7609bbe7df11e8a55f27a
有很多不同的方法可以实现代码提示/自动完成。
var arrows = [37, 38, 39, 40]
editor.on("keyup", function(cm, e)
if (arrows.indexOf(e.keyCode) < 0)
editor.execCommand("autocomplete")
)
当然 Codemirror 有 official documentation 用于代码提示/自动完成。XML completionHTML completionJavaScript completion
您也可以view the source 获取 javascript 示例来学习如何制作自己的提示。
【讨论】:
【参考方案4】:这就是我使用 CodeMirror 5 在我的应用程序 UI 中启用自定义代码提示的方式
(它基本上是由我在网上找到的几种解决方案和https://codemirror.net/demo/complete.html的源代码组成的大杂烩)
首先我添加了 CodeMirror 和代码提示插件
<script src="libs/codemirror-5/codemirror.min.js"></script>
<script src="libs/codemirror-5/plugins/show-hint.js"></script>
我重载了(正确的术语吗?)showHint
命令,将它放在一个函数中(注意,因为 CM 调用了这个函数,它会将实例上下文作为可用参数注入)。
function getSnippets(codemirror)
let snippets = [
text: 'SELECT', displayName: 'select',
text: 'UPDATE', displayName: 'update',
text: 'CREATE', displayName: 'create',
// other snippets for hinting
]
CodeMirror.showHint(codemirror, function ()
let cursor = codemirror.getCursor();
let line = codemirror.getLine(cursor.line);
let start = cursor.ch, end = cursor.ch;
// corrects ignoring trailing whitespaces removal
while (start && /\w/.test(line.charAt(start - 1)))
--start;
while (end < line.length && /\w/.test(line.charAt(end)))
++end;
const token = codemirror.getTokenAt(cursor);
const currentWord = token.string;
// reduce hint options if user has already entered something
const list = snippets.filter(function (item)
return item.displayText.indexOf(currentWord) >= 0;
);
return
list: list.length ? list : snippets,
from: CodeMirror.Pos(cursor.line, start),
to: CodeMirror.Pos(cursor.line, end)
;
, completeSingle: true);
然后,在 codemirror 实例选项中,我通过按 Ctrl+Space 定义了提示调用,这将调用我之前定义的 getSnippets
函数
let codemirrorOptions =
mode: 'sql',
extraKeys:
"Ctrl-Space": getSnippets
,
lineNumbers: false,
lineWrapping: true
;
【讨论】:
以上是关于如何使用 codemirror 启用代码提示?的主要内容,如果未能解决你的问题,请参考以下文章
当我使用 CodeMirror 在 TextArea 中编辑代码时,如何使用 js 或 jQuery 将其反映到另一个 textarea 中