commit
6504123d1b
@ -0,0 +1,33 @@
|
||||
$(document).on('turbolinks:load', function() {
|
||||
if ($('body.admins-mirror-scripts-edit-page, body.admins-mirror-scripts-update-page, body.admins-mirror-scripts-new-page, body.admins-mirror-scripts-create-page').length > 0) {
|
||||
var $form = $('form.script-form');
|
||||
|
||||
// codemirror编辑器
|
||||
var scriptEditor = CodeMirror.fromTextArea(document.getElementById('mirror_script_script'), {
|
||||
lineNumbers: true,
|
||||
mode: 'shell',
|
||||
theme: "default",
|
||||
indentUnit: 4, //代码缩进为一个tab的距离
|
||||
matchBrackets: true,
|
||||
autoRefresh: true,
|
||||
smartIndent: true,//智能换行
|
||||
styleActiveLine: true,
|
||||
lint: true
|
||||
});
|
||||
scriptEditor.setSize('auto', '600px');
|
||||
|
||||
$form.validate({
|
||||
errorElement: 'span',
|
||||
errorClass: 'danger text-danger',
|
||||
rules: {
|
||||
"mirror_script[script_type]": {
|
||||
required: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$form.submit(function(e){
|
||||
if(!$form.valid()){ e.preventDefault(); }
|
||||
});
|
||||
}
|
||||
});
|
@ -0,0 +1,59 @@
|
||||
class Admins::MirrorScriptsController < Admins::BaseController
|
||||
helper_method :current_mirror
|
||||
|
||||
def index
|
||||
scripts = current_mirror.mirror_scripts.order(updated_at: :desc)
|
||||
@scripts = paginate scripts
|
||||
end
|
||||
|
||||
def new
|
||||
@script = current_mirror.mirror_scripts.new
|
||||
end
|
||||
|
||||
def create
|
||||
@script = current_mirror.mirror_scripts.new(form_params)
|
||||
|
||||
if @script.save
|
||||
flash[:success] = '保存成功'
|
||||
redirect_to edit_admins_mirror_repository_mirror_script_path(current_mirror, @script)
|
||||
else
|
||||
flash[:danger] = '保存失败'
|
||||
render 'new'
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@script = current_script
|
||||
end
|
||||
|
||||
def update
|
||||
@script = current_script
|
||||
|
||||
if @script.update(form_params)
|
||||
flash[:success] = '保存成功'
|
||||
redirect_to edit_admins_mirror_repository_mirror_script_path(current_mirror, @script)
|
||||
else
|
||||
flash[:danger] = '保存失败'
|
||||
render 'edit'
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
current_script.destroy!
|
||||
render_delete_success
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_script
|
||||
@_current_script ||= current_mirror.mirror_scripts.find(params[:id])
|
||||
end
|
||||
|
||||
def current_mirror
|
||||
@_current_mirror ||= MirrorRepository.find(params[:mirror_repository_id])
|
||||
end
|
||||
|
||||
def form_params
|
||||
params.require(:mirror_script).permit(:script_type, :description, :script)
|
||||
end
|
||||
end
|
@ -0,0 +1,8 @@
|
||||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('镜像管理', admins_mirror_repositories_path) %>
|
||||
<% add_admin_breadcrumb(current_mirror.type_name, edit_admins_mirror_repository_path(current_mirror)) %>
|
||||
<% add_admin_breadcrumb('脚本列表', admins_mirror_repository_mirror_scripts_path(current_mirror)) %>
|
||||
<% add_admin_breadcrumb('编辑脚本') %>
|
||||
<% end %>
|
||||
|
||||
<%= render partial: 'admins/mirror_scripts/shared/form', locals: { mirror: current_mirror, script: @script, form_action: 'update' } %>
|
@ -0,0 +1,14 @@
|
||||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('镜像管理', admins_mirror_repositories_path) %>
|
||||
<% add_admin_breadcrumb(current_mirror.type_name, edit_admins_mirror_repository_path(current_mirror)) %>
|
||||
<% add_admin_breadcrumb('脚本列表') %>
|
||||
<% end %>
|
||||
|
||||
<div class="box search-form-container mirror-script-list-form">
|
||||
<form class="flex-1"></form>
|
||||
<%= link_to '新建', new_admins_mirror_repository_mirror_script_path(current_mirror), class: 'btn btn-primary' %>
|
||||
</div>
|
||||
|
||||
<div class="box mirror-script-list-container">
|
||||
<%= render partial: 'admins/mirror_scripts/shared/list', locals: { mirror: current_mirror, scripts: @scripts } %>
|
||||
</div>
|
@ -0,0 +1,8 @@
|
||||
<% define_admin_breadcrumbs do %>
|
||||
<% add_admin_breadcrumb('镜像管理', admins_mirror_repositories_path) %>
|
||||
<% add_admin_breadcrumb(current_mirror.type_name, edit_admins_mirror_repository_path(current_mirror)) %>
|
||||
<% add_admin_breadcrumb('脚本列表', admins_mirror_repository_mirror_scripts_path(current_mirror)) %>
|
||||
<% add_admin_breadcrumb('新建脚本') %>
|
||||
<% end %>
|
||||
|
||||
<%= render partial: 'admins/mirror_scripts/shared/form', locals: { mirror: current_mirror, script: @script, form_action: 'create' } %>
|
@ -0,0 +1,12 @@
|
||||
<div class="box edit-mirror-script-container">
|
||||
<%= simple_form_for([:admins, mirror, script], url: { action: form_action }, html: { class: 'script-form' }) do |f| %>
|
||||
<%= f.input :script_type, label: '名称', input_html: { class: 'col-md-6' } %>
|
||||
<%= f.input :description, as: :text, label: '说明', input_html: { class: 'col-md-6' } %>
|
||||
<%= f.input :script, as: :text, label: '评测脚本' %>
|
||||
|
||||
<div class="form-row">
|
||||
<%= f.button :submit, value: '保存', class: 'btn-primary mr-3 px-4', 'data-disable-with': '保存中...' %>
|
||||
<%= link_to '取消', admins_mirror_repository_mirror_scripts_path(mirror), class: 'btn btn-secondary px-4' %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
@ -0,0 +1,32 @@
|
||||
<table class="table table-hover text-center mirror-script-list-table">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th width="10%">ID</th>
|
||||
<th width="20%" class="text-left">名称</th>
|
||||
<th width="34%" class="text-left">说明</th>
|
||||
<th width="16%">更新时间</th>
|
||||
<th width="20%">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if scripts.present? %>
|
||||
<% scripts.each do |script| %>
|
||||
<tr class="mirror-script-item-<%= script.id %>">
|
||||
<td><%= script.id %></td>
|
||||
<td class="text-left"><%= overflow_hidden_span script.script_type, width: 200 %></td>
|
||||
<td class="text-left"><%= overflow_hidden_span script.description, width: 400 %></td>
|
||||
<td><%= script.updated_at.strftime('%Y-%m-%d %H:%M') %></td>
|
||||
<td class="action-container">
|
||||
<%= link_to '编辑', edit_admins_mirror_repository_mirror_script_path(mirror, script), class: 'action edit-action' %>
|
||||
|
||||
<%= delete_link '删除', admins_mirror_repository_mirror_script_path(mirror, script, element: ".mirror-script-item-#{script.id}"), class: 'delete-mirror-script-action' %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= render 'admins/shared/no_data_for_table' %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= render partial: 'admins/shared/paginate', locals: { objects: scripts } %>
|
@ -0,0 +1,6 @@
|
||||
<div class="d-flex flex-column align-items-center justify-content-center global-error">
|
||||
<div class="global-error-code">
|
||||
<span>403</span>
|
||||
</div>
|
||||
<div class="global-error-text">未授权</div>
|
||||
</div>
|
@ -1,2 +1,2 @@
|
||||
json.status 1
|
||||
json.message "创建参考答案成功"
|
||||
json.message "操作成功"
|
@ -1 +1 @@
|
||||
admins-users: admins-users
|
||||
admins-mirror_scripts: 'admins-mirror_repositories'
|
@ -0,0 +1,6 @@
|
||||
class AddUpdateUserIdToStudentWorks < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
add_column :student_works, :update_user_id, :integer
|
||||
StudentWork.update_all("update_user_id = commit_user_id")
|
||||
end
|
||||
end
|
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,349 @@
|
||||
/* BASICS */
|
||||
|
||||
.CodeMirror {
|
||||
/* Set height, width, borders, and global font properties here */
|
||||
font-family: monospace;
|
||||
height: 300px;
|
||||
color: black;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
/* PADDING */
|
||||
|
||||
.CodeMirror-lines {
|
||||
padding: 4px 0; /* Vertical padding around content */
|
||||
}
|
||||
.CodeMirror pre.CodeMirror-line,
|
||||
.CodeMirror pre.CodeMirror-line-like {
|
||||
padding: 0 4px; /* Horizontal padding of content */
|
||||
}
|
||||
|
||||
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||
background-color: white; /* The little square between H and V scrollbars */
|
||||
}
|
||||
|
||||
/* GUTTER */
|
||||
|
||||
.CodeMirror-gutters {
|
||||
border-right: 1px solid #ddd;
|
||||
background-color: #f7f7f7;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.CodeMirror-linenumbers {}
|
||||
.CodeMirror-linenumber {
|
||||
padding: 0 3px 0 5px;
|
||||
min-width: 20px;
|
||||
text-align: right;
|
||||
color: #999;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.CodeMirror-guttermarker { color: black; }
|
||||
.CodeMirror-guttermarker-subtle { color: #999; }
|
||||
|
||||
/* CURSOR */
|
||||
|
||||
.CodeMirror-cursor {
|
||||
border-left: 1px solid black;
|
||||
border-right: none;
|
||||
width: 0;
|
||||
}
|
||||
/* Shown when moving in bi-directional text */
|
||||
.CodeMirror div.CodeMirror-secondarycursor {
|
||||
border-left: 1px solid silver;
|
||||
}
|
||||
.cm-fat-cursor .CodeMirror-cursor {
|
||||
width: auto;
|
||||
border: 0 !important;
|
||||
background: #7e7;
|
||||
}
|
||||
.cm-fat-cursor div.CodeMirror-cursors {
|
||||
z-index: 1;
|
||||
}
|
||||
.cm-fat-cursor-mark {
|
||||
background-color: rgba(20, 255, 20, 0.5);
|
||||
-webkit-animation: blink 1.06s steps(1) infinite;
|
||||
-moz-animation: blink 1.06s steps(1) infinite;
|
||||
animation: blink 1.06s steps(1) infinite;
|
||||
}
|
||||
.cm-animate-fat-cursor {
|
||||
width: auto;
|
||||
border: 0;
|
||||
-webkit-animation: blink 1.06s steps(1) infinite;
|
||||
-moz-animation: blink 1.06s steps(1) infinite;
|
||||
animation: blink 1.06s steps(1) infinite;
|
||||
background-color: #7e7;
|
||||
}
|
||||
@-moz-keyframes blink {
|
||||
0% {}
|
||||
50% { background-color: transparent; }
|
||||
100% {}
|
||||
}
|
||||
@-webkit-keyframes blink {
|
||||
0% {}
|
||||
50% { background-color: transparent; }
|
||||
100% {}
|
||||
}
|
||||
@keyframes blink {
|
||||
0% {}
|
||||
50% { background-color: transparent; }
|
||||
100% {}
|
||||
}
|
||||
|
||||
/* Can style cursor different in overwrite (non-insert) mode */
|
||||
.CodeMirror-overwrite .CodeMirror-cursor {}
|
||||
|
||||
.cm-tab { display: inline-block; text-decoration: inherit; }
|
||||
|
||||
.CodeMirror-rulers {
|
||||
position: absolute;
|
||||
left: 0; right: 0; top: -50px; bottom: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.CodeMirror-ruler {
|
||||
border-left: 1px solid #ccc;
|
||||
top: 0; bottom: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* DEFAULT THEME */
|
||||
|
||||
.cm-s-default .cm-header {color: blue;}
|
||||
.cm-s-default .cm-quote {color: #090;}
|
||||
.cm-negative {color: #d44;}
|
||||
.cm-positive {color: #292;}
|
||||
.cm-header, .cm-strong {font-weight: bold;}
|
||||
.cm-em {font-style: italic;}
|
||||
.cm-link {text-decoration: underline;}
|
||||
.cm-strikethrough {text-decoration: line-through;}
|
||||
|
||||
.cm-s-default .cm-keyword {color: #708;}
|
||||
.cm-s-default .cm-atom {color: #219;}
|
||||
.cm-s-default .cm-number {color: #164;}
|
||||
.cm-s-default .cm-def {color: #00f;}
|
||||
.cm-s-default .cm-variable,
|
||||
.cm-s-default .cm-punctuation,
|
||||
.cm-s-default .cm-property,
|
||||
.cm-s-default .cm-operator {}
|
||||
.cm-s-default .cm-variable-2 {color: #05a;}
|
||||
.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}
|
||||
.cm-s-default .cm-comment {color: #a50;}
|
||||
.cm-s-default .cm-string {color: #a11;}
|
||||
.cm-s-default .cm-string-2 {color: #f50;}
|
||||
.cm-s-default .cm-meta {color: #555;}
|
||||
.cm-s-default .cm-qualifier {color: #555;}
|
||||
.cm-s-default .cm-builtin {color: #30a;}
|
||||
.cm-s-default .cm-bracket {color: #997;}
|
||||
.cm-s-default .cm-tag {color: #170;}
|
||||
.cm-s-default .cm-attribute {color: #00c;}
|
||||
.cm-s-default .cm-hr {color: #999;}
|
||||
.cm-s-default .cm-link {color: #00c;}
|
||||
|
||||
.cm-s-default .cm-error {color: #f00;}
|
||||
.cm-invalidchar {color: #f00;}
|
||||
|
||||
.CodeMirror-composing { border-bottom: 2px solid; }
|
||||
|
||||
/* Default styles for common addons */
|
||||
|
||||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}
|
||||
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
|
||||
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
|
||||
.CodeMirror-activeline-background {background: #e8f2ff;}
|
||||
|
||||
/* STOP */
|
||||
|
||||
/* The rest of this file contains styles related to the mechanics of
|
||||
the editor. You probably shouldn't touch them. */
|
||||
|
||||
.CodeMirror {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll {
|
||||
overflow: scroll !important; /* Things will break if this is overridden */
|
||||
/* 30px is the magic margin used to hide the element's real scrollbars */
|
||||
/* See overflow: hidden in .CodeMirror */
|
||||
margin-bottom: -30px; margin-right: -30px;
|
||||
padding-bottom: 30px;
|
||||
height: 100%;
|
||||
outline: none; /* Prevent dragging from highlighting the element */
|
||||
position: relative;
|
||||
}
|
||||
.CodeMirror-sizer {
|
||||
position: relative;
|
||||
border-right: 30px solid transparent;
|
||||
}
|
||||
|
||||
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||
before actual scrolling happens, thus preventing shaking and
|
||||
flickering artifacts. */
|
||||
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
display: none;
|
||||
}
|
||||
.CodeMirror-vscrollbar {
|
||||
right: 0; top: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.CodeMirror-hscrollbar {
|
||||
bottom: 0; left: 0;
|
||||
overflow-y: hidden;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
.CodeMirror-scrollbar-filler {
|
||||
right: 0; bottom: 0;
|
||||
}
|
||||
.CodeMirror-gutter-filler {
|
||||
left: 0; bottom: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
position: absolute; left: 0; top: 0;
|
||||
min-height: 100%;
|
||||
z-index: 3;
|
||||
}
|
||||
.CodeMirror-gutter {
|
||||
white-space: normal;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-bottom: -30px;
|
||||
}
|
||||
.CodeMirror-gutter-wrapper {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
background: none !important;
|
||||
border: none !important;
|
||||
}
|
||||
.CodeMirror-gutter-background {
|
||||
position: absolute;
|
||||
top: 0; bottom: 0;
|
||||
z-index: 4;
|
||||
}
|
||||
.CodeMirror-gutter-elt {
|
||||
position: absolute;
|
||||
cursor: default;
|
||||
z-index: 4;
|
||||
}
|
||||
.CodeMirror-gutter-wrapper ::selection { background-color: transparent }
|
||||
.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
|
||||
|
||||
.CodeMirror-lines {
|
||||
cursor: text;
|
||||
min-height: 1px; /* prevents collapsing before first draw */
|
||||
}
|
||||
.CodeMirror pre.CodeMirror-line,
|
||||
.CodeMirror pre.CodeMirror-line-like {
|
||||
/* Reset some styles that the rest of the page might have set */
|
||||
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
|
||||
border-width: 0;
|
||||
background: transparent;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
margin: 0;
|
||||
white-space: pre;
|
||||
word-wrap: normal;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-font-variant-ligatures: contextual;
|
||||
font-variant-ligatures: contextual;
|
||||
}
|
||||
.CodeMirror-wrap pre.CodeMirror-line,
|
||||
.CodeMirror-wrap pre.CodeMirror-line-like {
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
.CodeMirror-linebackground {
|
||||
position: absolute;
|
||||
left: 0; right: 0; top: 0; bottom: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-linewidget {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: 0.1px; /* Force widget margins to stay inside of the container */
|
||||
}
|
||||
|
||||
.CodeMirror-widget {}
|
||||
|
||||
.CodeMirror-rtl pre { direction: rtl; }
|
||||
|
||||
.CodeMirror-code {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Force content-box sizing for the elements where we expect it */
|
||||
.CodeMirror-scroll,
|
||||
.CodeMirror-sizer,
|
||||
.CodeMirror-gutter,
|
||||
.CodeMirror-gutters,
|
||||
.CodeMirror-linenumber {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.CodeMirror-measure {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-cursor {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
.CodeMirror-measure pre { position: static; }
|
||||
|
||||
div.CodeMirror-cursors {
|
||||
visibility: hidden;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
}
|
||||
div.CodeMirror-dragcursors {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-focused div.CodeMirror-cursors {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-selected { background: #d9d9d9; }
|
||||
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
|
||||
.CodeMirror-crosshair { cursor: crosshair; }
|
||||
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
|
||||
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
|
||||
|
||||
.cm-searching {
|
||||
background-color: #ffa;
|
||||
background-color: rgba(255, 255, 0, .4);
|
||||
}
|
||||
|
||||
/* Used to force a border model for a node */
|
||||
.cm-force-border { padding-right: .1px; }
|
||||
|
||||
@media print {
|
||||
/* Hide the cursor when printing */
|
||||
.CodeMirror div.CodeMirror-cursors {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
/* See issue #2901 */
|
||||
.cm-tab-wrap-hack:after { content: ''; }
|
||||
|
||||
/* Help users use markselection to safely style text background */
|
||||
span.CodeMirror-selectedtext { background: none; }
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,152 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode('shell', function() {
|
||||
|
||||
var words = {};
|
||||
function define(style, dict) {
|
||||
for(var i = 0; i < dict.length; i++) {
|
||||
words[dict[i]] = style;
|
||||
}
|
||||
};
|
||||
|
||||
var commonAtoms = ["true", "false"];
|
||||
var commonKeywords = ["if", "then", "do", "else", "elif", "while", "until", "for", "in", "esac", "fi",
|
||||
"fin", "fil", "done", "exit", "set", "unset", "export", "function"];
|
||||
var commonCommands = ["ab", "awk", "bash", "beep", "cat", "cc", "cd", "chown", "chmod", "chroot", "clear",
|
||||
"cp", "curl", "cut", "diff", "echo", "find", "gawk", "gcc", "get", "git", "grep", "hg", "kill", "killall",
|
||||
"ln", "ls", "make", "mkdir", "openssl", "mv", "nc", "nl", "node", "npm", "ping", "ps", "restart", "rm",
|
||||
"rmdir", "sed", "service", "sh", "shopt", "shred", "source", "sort", "sleep", "ssh", "start", "stop",
|
||||
"su", "sudo", "svn", "tee", "telnet", "top", "touch", "vi", "vim", "wall", "wc", "wget", "who", "write",
|
||||
"yes", "zsh"];
|
||||
|
||||
CodeMirror.registerHelper("hintWords", "shell", commonAtoms.concat(commonKeywords, commonCommands));
|
||||
|
||||
define('atom', commonAtoms);
|
||||
define('keyword', commonKeywords);
|
||||
define('builtin', commonCommands);
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
if (stream.eatSpace()) return null;
|
||||
|
||||
var sol = stream.sol();
|
||||
var ch = stream.next();
|
||||
|
||||
if (ch === '\\') {
|
||||
stream.next();
|
||||
return null;
|
||||
}
|
||||
if (ch === '\'' || ch === '"' || ch === '`') {
|
||||
state.tokens.unshift(tokenString(ch, ch === "`" ? "quote" : "string"));
|
||||
return tokenize(stream, state);
|
||||
}
|
||||
if (ch === '#') {
|
||||
if (sol && stream.eat('!')) {
|
||||
stream.skipToEnd();
|
||||
return 'meta'; // 'comment'?
|
||||
}
|
||||
stream.skipToEnd();
|
||||
return 'comment';
|
||||
}
|
||||
if (ch === '$') {
|
||||
state.tokens.unshift(tokenDollar);
|
||||
return tokenize(stream, state);
|
||||
}
|
||||
if (ch === '+' || ch === '=') {
|
||||
return 'operator';
|
||||
}
|
||||
if (ch === '-') {
|
||||
stream.eat('-');
|
||||
stream.eatWhile(/\w/);
|
||||
return 'attribute';
|
||||
}
|
||||
if (/\d/.test(ch)) {
|
||||
stream.eatWhile(/\d/);
|
||||
if(stream.eol() || !/\w/.test(stream.peek())) {
|
||||
return 'number';
|
||||
}
|
||||
}
|
||||
stream.eatWhile(/[\w-]/);
|
||||
var cur = stream.current();
|
||||
if (stream.peek() === '=' && /\w+/.test(cur)) return 'def';
|
||||
return words.hasOwnProperty(cur) ? words[cur] : null;
|
||||
}
|
||||
|
||||
function tokenString(quote, style) {
|
||||
var close = quote == "(" ? ")" : quote == "{" ? "}" : quote
|
||||
return function(stream, state) {
|
||||
var next, escaped = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next === close && !escaped) {
|
||||
state.tokens.shift();
|
||||
break;
|
||||
} else if (next === '$' && !escaped && quote !== "'" && stream.peek() != close) {
|
||||
escaped = true;
|
||||
stream.backUp(1);
|
||||
state.tokens.unshift(tokenDollar);
|
||||
break;
|
||||
} else if (!escaped && quote !== close && next === quote) {
|
||||
state.tokens.unshift(tokenString(quote, style))
|
||||
return tokenize(stream, state)
|
||||
} else if (!escaped && /['"]/.test(next) && !/['"]/.test(quote)) {
|
||||
state.tokens.unshift(tokenStringStart(next, "string"));
|
||||
stream.backUp(1);
|
||||
break;
|
||||
}
|
||||
escaped = !escaped && next === '\\';
|
||||
}
|
||||
return style;
|
||||
};
|
||||
};
|
||||
|
||||
function tokenStringStart(quote, style) {
|
||||
return function(stream, state) {
|
||||
state.tokens[0] = tokenString(quote, style)
|
||||
stream.next()
|
||||
return tokenize(stream, state)
|
||||
}
|
||||
}
|
||||
|
||||
var tokenDollar = function(stream, state) {
|
||||
if (state.tokens.length > 1) stream.eat('$');
|
||||
var ch = stream.next()
|
||||
if (/['"({]/.test(ch)) {
|
||||
state.tokens[0] = tokenString(ch, ch == "(" ? "quote" : ch == "{" ? "def" : "string");
|
||||
return tokenize(stream, state);
|
||||
}
|
||||
if (!/\d/.test(ch)) stream.eatWhile(/\w/);
|
||||
state.tokens.shift();
|
||||
return 'def';
|
||||
};
|
||||
|
||||
function tokenize(stream, state) {
|
||||
return (state.tokens[0] || tokenBase) (stream, state);
|
||||
};
|
||||
|
||||
return {
|
||||
startState: function() {return {tokens:[]};},
|
||||
token: function(stream, state) {
|
||||
return tokenize(stream, state);
|
||||
},
|
||||
closeBrackets: "()[]{}''\"\"``",
|
||||
lineComment: '#',
|
||||
fold: "brace"
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME('text/x-sh', 'shell');
|
||||
// Apache uses a slightly different Media Type for Shell scripts
|
||||
// http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types
|
||||
CodeMirror.defineMIME('application/x-sh', 'shell');
|
||||
|
||||
});
|
Loading…
Reference in new issue