// Copyright (C) 2014 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package net.codemirror.mode; import com.google.gerrit.client.rpc.NativeMap; import com.google.gerrit.client.rpc.Natives; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.JsArrayString; import com.google.gwt.resources.client.DataResource; import com.google.gwt.safehtml.shared.SafeUri; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Map; /** Description of a CodeMirror language mode. */ public class ModeInfo extends JavaScriptObject { private static NativeMap<ModeInfo> byMime; private static NativeMap<ModeInfo> byExt; /** Map of names such as "clike" to URI for code download. */ private static final Map<String, SafeUri> modeUris = new HashMap<>(); static { indexModes( new DataResource[] { Modes.I.apl(), Modes.I.asciiarmor(), Modes.I.asn_1(), Modes.I.asterisk(), Modes.I.brainfuck(), Modes.I.clike(), Modes.I.clojure(), Modes.I.cmake(), Modes.I.cobol(), Modes.I.coffeescript(), Modes.I.commonlisp(), Modes.I.crystal(), Modes.I.css(), Modes.I.cypher(), Modes.I.d(), Modes.I.dart(), Modes.I.diff(), Modes.I.django(), Modes.I.dockerfile(), Modes.I.dtd(), Modes.I.dylan(), Modes.I.ebnf(), Modes.I.ecl(), Modes.I.eiffel(), Modes.I.elm(), Modes.I.erlang(), Modes.I.factor(), Modes.I.fcl(), Modes.I.forth(), Modes.I.fortran(), Modes.I.gas(), Modes.I.gerrit_commit(), Modes.I.gfm(), Modes.I.gherkin(), Modes.I.go(), Modes.I.groovy(), Modes.I.haml(), Modes.I.handlebars(), Modes.I.haskell_literate(), Modes.I.haskell(), Modes.I.haxe(), Modes.I.htmlembedded(), Modes.I.htmlmixed(), Modes.I.http(), Modes.I.idl(), Modes.I.javascript(), Modes.I.jinja2(), Modes.I.jsx(), Modes.I.julia(), Modes.I.livescript(), Modes.I.lua(), Modes.I.markdown(), Modes.I.mathematica(), Modes.I.mbox(), Modes.I.mirc(), Modes.I.mllike(), Modes.I.modelica(), Modes.I.mscgen(), Modes.I.mumps(), Modes.I.nginx(), Modes.I.nsis(), Modes.I.ntriples(), Modes.I.octave(), Modes.I.oz(), Modes.I.pascal(), Modes.I.pegjs(), Modes.I.perl(), Modes.I.php(), Modes.I.pig(), Modes.I.powershell(), Modes.I.properties(), Modes.I.protobuf(), Modes.I.pug(), Modes.I.puppet(), Modes.I.python(), Modes.I.q(), Modes.I.r(), Modes.I.rpm(), Modes.I.rst(), Modes.I.ruby(), Modes.I.rust(), Modes.I.sas(), Modes.I.sass(), Modes.I.scheme(), Modes.I.shell(), Modes.I.smalltalk(), Modes.I.smarty(), Modes.I.solr(), Modes.I.soy(), Modes.I.sparql(), Modes.I.spreadsheet(), Modes.I.sql(), Modes.I.stex(), Modes.I.stylus(), Modes.I.swift(), Modes.I.tcl(), Modes.I.textile(), Modes.I.tiddlywiki(), Modes.I.tiki(), Modes.I.toml(), Modes.I.tornado(), Modes.I.troff(), Modes.I.ttcn_cfg(), Modes.I.ttcn(), Modes.I.turtle(), Modes.I.twig(), Modes.I.vb(), Modes.I.vbscript(), Modes.I.velocity(), Modes.I.verilog(), Modes.I.vhdl(), Modes.I.vue(), Modes.I.webidl(), Modes.I.xml(), Modes.I.xquery(), Modes.I.yacas(), Modes.I.yaml_frontmatter(), Modes.I.yaml(), Modes.I.z80(), }); alias("application/x-httpd-php-open", "application/x-httpd-php"); alias("application/x-javascript", "application/javascript"); alias("application/x-shellscript", "text/x-sh"); alias("application/x-tcl", "text/x-tcl"); alias("text/typescript", "application/typescript"); alias("text/x-c", "text/x-csrc"); alias("text/x-c++hdr", "text/x-c++src"); alias("text/x-chdr", "text/x-csrc"); alias("text/x-h", "text/x-csrc"); alias("text/x-ini", "text/x-properties"); alias("text/x-java-source", "text/x-java"); alias("text/x-php", "application/x-httpd-php"); alias("text/x-scripttcl", "text/x-tcl"); } /** All supported modes. */ public static native JsArray<ModeInfo> all() /*-{ return $wnd.CodeMirror.modeInfo }-*/; private static native void setAll(JsArray<ModeInfo> m) /*-{ $wnd.CodeMirror.modeInfo = m }-*/; /** Look up mode by primary or alternate MIME types. */ public static ModeInfo findModeByMIME(String mime) { return byMime.get(mime); } public static SafeUri getModeScriptUri(String mode) { return modeUris.get(mode); } /** Look up mode by MIME type or file extension from a path. */ public static ModeInfo findMode(String mime, String path) { ModeInfo m = byMime.get(mime); if (m != null) { return m; } int s = path.lastIndexOf('/'); int d = path.lastIndexOf('.'); if (d == -1 || s > d) { return null; // punt on "foo.src/bar" type paths. } if (byExt == null) { byExt = NativeMap.create(); for (ModeInfo mode : Natives.asList(all())) { for (String ext : Natives.asList(mode.ext())) { byExt.put(ext, mode); } } } return byExt.get(path.substring(d + 1)); } private static void alias(String serverMime, String toMime) { ModeInfo mode = byMime.get(toMime); if (mode != null) { byMime.put(serverMime, mode); } } private static void indexModes(DataResource[] all) { for (DataResource r : all) { modeUris.put(r.getName(), r.getSafeUri()); } JsArray<ModeInfo> modeList = all(); modeList.push(gerrit_commit()); byMime = NativeMap.create(); JsArray<ModeInfo> filtered = JsArray.createArray().cast(); for (ModeInfo m : Natives.asList(modeList)) { if (modeUris.containsKey(m.mode())) { filtered.push(m); for (String mimeType : Natives.asList(m.mimes())) { byMime.put(mimeType, m); } byMime.put(m.mode(), m); } } Collections.sort( Natives.asList(filtered), new Comparator<ModeInfo>() { @Override public int compare(ModeInfo a, ModeInfo b) { return a.name().toLowerCase().compareTo(b.name().toLowerCase()); } }); setAll(filtered); } /** Human readable name of the mode, such as "C++". */ public final native String name() /*-{ return this.name }-*/; /** Internal CodeMirror name for {@code mode.js} file to load. */ public final native String mode() /*-{ return this.mode }-*/; /** Primary MIME type to activate this mode. */ public final native String mime() /*-{ return this.mime }-*/; /** Primary and additional MIME types that activate this mode. */ public final native JsArrayString mimes() /*-{ return this.mimes || [this.mime] }-*/; private native JsArrayString ext() /*-{ return this.ext || [] }-*/; protected ModeInfo() {} private static native ModeInfo gerrit_commit() /*-{ return {name: "Git Commit Message", mime: "text/x-gerrit-commit-message", mode: "gerrit_commit"} }-*/; }