Browse Source

Bug 27643: Add CodeMirror custom syntax highlighting for SQL runtime parameters

This patch adds some additional configuration to CodeMirror so that
runtime parameters have a distinct color in the CodeMirror SQL editor.

To test, apply the patch and create or edit an SQL report which contains
one or more runtime parameters, e.g. <<branches>>, <<categorycode>>,
etc.

Confirm that when editing the SQL, these parameters should appear as
green text. Save your report and view it. The syntax highlighting should
be updated in this view too.

Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
21.05.x
Owen Leonard 2 years ago
committed by Jonathan Druart
parent
commit
58cc70a0cb
  1. 90
      koha-tmpl/intranet-tmpl/lib/codemirror/overlay.js
  2. 1
      koha-tmpl/intranet-tmpl/lib/codemirror/overlay.min.js
  3. 30
      koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt

90
koha-tmpl/intranet-tmpl/lib/codemirror/overlay.js

@ -0,0 +1,90 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Utility function that allows modes to be combined. The mode given
// as the base argument takes care of most of the normal mode
// functionality, but a second (typically simple) mode is used, which
// can override the style of text. Both modes get to parse all of the
// text, but when both assign a non-null style to a piece of code, the
// overlay wins, unless the combine argument was true and not overridden,
// or state.overlay.combineTokens was true, in which case the styles are
// combined.
(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.overlayMode = function(base, overlay, combine) {
return {
startState: function() {
return {
base: CodeMirror.startState(base),
overlay: CodeMirror.startState(overlay),
basePos: 0, baseCur: null,
overlayPos: 0, overlayCur: null,
streamSeen: null
};
},
copyState: function(state) {
return {
base: CodeMirror.copyState(base, state.base),
overlay: CodeMirror.copyState(overlay, state.overlay),
basePos: state.basePos, baseCur: null,
overlayPos: state.overlayPos, overlayCur: null
};
},
token: function(stream, state) {
if (stream != state.streamSeen ||
Math.min(state.basePos, state.overlayPos) < stream.start) {
state.streamSeen = stream;
state.basePos = state.overlayPos = stream.start;
}
if (stream.start == state.basePos) {
state.baseCur = base.token(stream, state.base);
state.basePos = stream.pos;
}
if (stream.start == state.overlayPos) {
stream.pos = stream.start;
state.overlayCur = overlay.token(stream, state.overlay);
state.overlayPos = stream.pos;
}
stream.pos = Math.min(state.basePos, state.overlayPos);
// state.overlay.combineTokens always takes precedence over combine,
// unless set to null
if (state.overlayCur == null) return state.baseCur;
else if (state.baseCur != null &&
state.overlay.combineTokens ||
combine && state.overlay.combineTokens == null)
return state.baseCur + " " + state.overlayCur;
else return state.overlayCur;
},
indent: base.indent && function(state, textAfter) {
return base.indent(state.base, textAfter);
},
electricChars: base.electricChars,
innerMode: function(state) { return {state: state.base, mode: base}; },
blankLine: function(state) {
var baseToken, overlayToken;
if (base.blankLine) baseToken = base.blankLine(state.base);
if (overlay.blankLine) overlayToken = overlay.blankLine(state.overlay);
return overlayToken == null ?
baseToken :
(combine && baseToken != null ? baseToken + " " + overlayToken : overlayToken);
}
};
};
});

1
koha-tmpl/intranet-tmpl/lib/codemirror/overlay.min.js

@ -0,0 +1 @@
!function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.overlayMode=function(o,r,a){return{startState:function(){return{base:e.startState(o),overlay:e.startState(r),basePos:0,baseCur:null,overlayPos:0,overlayCur:null,streamSeen:null}},copyState:function(a){return{base:e.copyState(o,a.base),overlay:e.copyState(r,a.overlay),basePos:a.basePos,baseCur:null,overlayPos:a.overlayPos,overlayCur:null}},token:function(e,n){return(e!=n.streamSeen||Math.min(n.basePos,n.overlayPos)<e.start)&&(n.streamSeen=e,n.basePos=n.overlayPos=e.start),e.start==n.basePos&&(n.baseCur=o.token(e,n.base),n.basePos=e.pos),e.start==n.overlayPos&&(e.pos=e.start,n.overlayCur=r.token(e,n.overlay),n.overlayPos=e.pos),e.pos=Math.min(n.basePos,n.overlayPos),null==n.overlayCur?n.baseCur:null!=n.baseCur&&n.overlay.combineTokens||a&&null==n.overlay.combineTokens?n.baseCur+" "+n.overlayCur:n.overlayCur},indent:o.indent&&function(e,r){return o.indent(e.base,r)},electricChars:o.electricChars,innerMode:function(e){return{state:e.base,mode:o}},blankLine:function(e){var n,t;return o.blankLine&&(n=o.blankLine(e.base)),r.blankLine&&(t=r.blankLine(e.overlay)),null==t?n:a&&null!=n?n+" "+t:t}}}});

30
koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt

@ -53,6 +53,9 @@
.CodeMirror {
resize: vertical;
}
.cm-sqlParams {
color: #11917B;
}
#mana_search_errortext { font-family: monospace; font-weight: bold; }
</style>
[% Asset.css("css/reports.css") | $raw %]
@ -1293,7 +1296,7 @@
[% INCLUDE 'guided-reports-view.inc' %]
</aside>
</div> <!-- /.col-sm-2.col-sm-pull-10 -->
</div> <!-- /.row -->
</div> <!-- /.row -->
[% MACRO jsinclude BLOCK %]
[% Asset.js("js/charts.js") | $raw %]
@ -1305,6 +1308,7 @@
[% INCLUDE 'columns_settings.inc' %]
[% END %]
[% Asset.js( "lib/codemirror/codemirror.min.js" ) | $raw %]
[% Asset.js( "lib/codemirror/overlay.min.js" ) | $raw %]
[% Asset.js( "lib/codemirror/sql.min.js" ) | $raw %]
[% Asset.js( "js/mana.js" ) | $raw %]
<script>
@ -1337,6 +1341,25 @@
}
}
/* overlay a syntax-highlighting definition on top of the existing sql one */
CodeMirror.defineMode("sqlParams", function(config, parserConfig) {
var sqlParamsOverlay = {
token: function(stream, state) {
var ch;
if (stream.match("<<")) {
while ((ch = stream.next()) != null)
if (ch == ">" && stream.next() == ">") {
stream.eat(">");
return "sqlParams";
}
}
while (stream.next() != null && !stream.match("<<", false)) {}
return null;
}
};
return CodeMirror.overlayMode(CodeMirror.getMode(config, parserConfig.backdrop || "text/x-sql"), sqlParamsOverlay);
});
var MSG_CONFIRM_DELETE = _("Are you sure you want to delete this report? This cannot be undone.");
var group_subgroups = {};
[% FOREACH group IN groups_with_subgroups %]
@ -1350,9 +1373,10 @@
[% END %]
[% IF ( create || editsql || save ) %]
var editor = CodeMirror.fromTextArea(sql, {
lineNumbers: true,
mode: "text/x-sql",
mode: "sqlParams", /* text/x-sql plus custom sqlParams configuration */
lineWrapping: true,
smartIndent: false
});
@ -1374,7 +1398,7 @@
[% IF ( showsql ) %]
var editor = CodeMirror.fromTextArea(sql, {
lineNumbers: false,
mode: "text/x-sql",
mode: "sqlParams", /* text/x-sql plus custom sqlParams configuration */
lineWrapping: true,
readOnly: true
});

Loading…
Cancel
Save