本网站在2019年8月12日之前用的代码演示功能是借用了 https://tool.lu/coderunner/ 的在线运行代码工具,在此致谢。
有一段时间这个工具突然失效了,我就在想能不能自己模仿着做一个类似的出来,简单分析了一下就想挑战一下自己,然后就开始动手了。
做出来的成果链接:点击此处
做的过程中查阅了很多网络资料,现整理如下:
需求分析:前端为一个实用的代码编辑器,通过ajax请求将写好的代码提交给服务器,服务器编译运行后把输出结果送回客户端显示。
其中使用的代码编辑器:CodeMirror,现在类似的工具使用的应该都是这款功能强大,可以自定样式的代码编辑器,官网: https://codemirror.net/
CodeMirror搭建前端界面
先从官网下载下来CodeMirror的压缩包,解压之后得到下图目录
要在html中创建一个CodeMirror编辑器,必须添加的css和js文件是
<link href=./codemirror-5.48.2/lib/codemirror.css rel=stylesheet/>
<script src=./codemirror-5.48.2/lib/codemirror.js></script>
(5.48.2为版本号,因人而异)
然后需要添加需要编辑的语言相关的js文件,可以在mode目录下找到,这里我用了两个文件:
实现JAVA和C++代码高亮(这个文件可以实现C,C++,JAVA,C#等语言):
<script src=./codemirror-5.48.2/mode/clike/clike.js></script>
实现python的代码高亮:
<script src=./codemirror-5.48.2/mode/python/python.js></script>
需要更改编辑器主题样式的可以在theme目录下找到对应的主题css文件添加进去,我觉得默认主题就很好看了就没用其他主题。
为了实现括号匹配和代码折叠功能,还要添加的文件有:
<link rel=stylesheet href=./codemirror-5.48.2/addon/fold/foldgutter.css/>
<script src=./codemirror-5.48.2/addon/fold/foldcode.js></script>
<script src=./codemirror-5.48.2/addon/fold/foldgutter.js></script>
<script src=./codemirror-5.48.2/addon/fold/brace-fold.js></script>
<script src=./codemirror-5.48.2/addon/fold/comment-fold.js></script>
创建编辑器的过程:
在html中使用一个textarea占位,配置好id:
<textarea id=code name=code></textarea>
通过对应的js代码创建编辑器:
var editor = CodeMirror.fromTextArea(document.getElementById(code), {
mode: text/x-java, //实现Java代码高亮
//mode: text/x-c++src, //实现C++代码高亮
//mode: text/x-python, //实现Python代码高亮
indentUnit:4,//以四个空格的长度缩进
indentWithTabs: true,//以tab代替空格缩进
lineNumbers: true, //显示行号
lineWrapping: true,
foldGutter: true, //代码折叠
gutters: [CodeMirror-linenumbers, CodeMirror-foldgutter],
matchBrackets: true //括号匹配
});
这里需要什么语言高亮需要在官网找到对应语言的 MIME types ,写在mode参数中
其他相关js函数:
编辑器的大小通过 editor.setSize(width, height)
方法设置
获取编辑器内的代码:editor.getValue()
设置编辑器内的代码:editor.setValue()
设置编辑器的配置选项: editor.setOption()
最终搭配上bootstrap样式做出来的效果是这样的:
js实现前端逻辑
使用JQuery简化js的写法
关键代码:
切换语言事件
//选择语言事件
$("#lang").on('change', () => {
lang = $("#lang").val()
if (lang == 'java') {
editor.setOption("mode", "text/x-java")
editor.setValue(javacode)
} else if (lang == "cpp") {
editor.setOption("mode", "text/x-c++src")
editor.setValue(cppcode)
} else if (lang == "python") {
editor.setOption("mode", "text/x-python")
editor.setValue(pythoncode)
}
})
发送POST请求
$(function(){
//点击运行按钮后的事件
$("#run").on("click",()=>{
var codesrc = editor.getValue();
//给源代码编码
var codeEncoded = encodeURIComponent(codesrc);
$("output").html = 'console>>' + '正在努力执行中...';
//发出post请求
$.post( "/runcode.php", { lang:lang,codesrc:codeEncoded }, (data)=>{
var outputs = data.output;
var status1 = data.status1;
var output = '';
//拼接输出结果
if(status1 !== 1){
for(var i in outputs)
{
output = output + outputs[i] + '<br/>';
}data
}else{
var outputs1 = data.output1;
for(var i in outputs1)
{
output = output + outputs1[i] + '<br/>';
}
}
$("output").html = 'console>>' + output;
}, "json");
})
});
注: 由于代码中可能出现 +
或 &
等符号,其在post的请求中经过urlencode会分别被解析为空格和参数连接符,需先将代码源码用js的encodeURIComponent()
函数编码,传递到php后端后再用rawurldecode()
函数进行解码操作。
php实现后端
php的任务是在服务器上运行代码,核心的思想是将接收到的代码写入文件,使用各种环境去执行,并返回结果
其中用到了exec函数
具体参阅 【php】php使用exec总结
做的时候遇到了个问题:php在调用exec执行gcc命令时,会出现各种毛病,例如ld链接器找不到,后来发现原因是php不会使用系统设置的环境变量,在php文件开头添加这样一句话就能解决问题:
putenv(PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin);//设置环境变量
原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/%e5%9c%a8%e7%ba%bf%e8%bf%90%e8%a1%8cc%e3%80%81java%e3%80%81python%e4%bb%a3%e7%a0%81%e7%9a%84%e5%b0%8f%e9%a1%b9%e7%9b%ae%e5%ae%9e%e7%8e%b0/