diff --git a/.gitmodules b/.gitmodules index a70edd8091..6c9e3ccefa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -536,6 +536,9 @@ [submodule "vendor/grammars/language-html"] path = vendor/grammars/language-html url = https://github.com/atom/language-html +[submodule "vendor/grammars/language-igor"] + path = vendor/grammars/language-igor + url = https://github.com/byte-physics/language-igor [submodule "vendor/grammars/language-inform7"] path = vendor/grammars/language-inform7 url = https://github.com/erkyrath/language-inform7 diff --git a/grammars.yml b/grammars.yml index e29783f528..0f8fa4847e 100755 --- a/grammars.yml +++ b/grammars.yml @@ -471,6 +471,8 @@ vendor/grammars/language-hql: - source.hql vendor/grammars/language-html: - text.html.basic +vendor/grammars/language-igor: +- source.igor vendor/grammars/language-inform7: - source.inform7 vendor/grammars/language-javascript: diff --git a/lib/linguist/languages.yml b/lib/linguist/languages.yml index 4f6e832aac..304115e816 100755 --- a/lib/linguist/languages.yml +++ b/lib/linguist/languages.yml @@ -2100,12 +2100,13 @@ IDL: language_id: 161 IGOR Pro: type: programming + color: "#0000cc" extensions: - ".ipf" aliases: - igor - igorpro - tm_scope: none + tm_scope: source.igor ace_mode: text language_id: 162 INI: diff --git a/samples/IGOR Pro/CodeBrowser.ipf b/samples/IGOR Pro/CodeBrowser.ipf new file mode 100644 index 0000000000..d108f2c622 --- /dev/null +++ b/samples/IGOR Pro/CodeBrowser.ipf @@ -0,0 +1,221 @@ +#pragma rtGlobals=3 +#pragma version=1.3 +#pragma IgorVersion = 6.3.0 +#pragma IndependentModule=CodeBrowserModule + +#include "CodeBrowser_gui" +#include + +// Copyright (c) 2019, () byte physics support@byte-physics.de +// All rights reserved. +// +// This source code is licensed under the BSD 3-Clause license found in the +// LICENSE file in the root directory of this source tree. +// +// source: https://github.com/byte-physics/igor-code-browser/blob/6a1497795f606d9d837d4012cbb4bbc481af3683/procedures/CodeBrowser.ipf + +Menu "CodeBrowser" + // CTRL+0 is the keyboard shortcut + "Open/0", /Q, CodeBrowserModule#CreatePanel() + "Reset", /Q, CodeBrowserModule#ResetPanel() +End + +// Markers for the different listbox elements +StrConstant strConstantMarker = "\\W539" +StrConstant constantMarker = "\\W534" + +Function addDecoratedStructure(text, declWave, lineWave, [parseVariables]) + WAVE/T text + WAVE/T declWave + WAVE/D lineWave + Variable parseVariables + if(paramIsDefault(parseVariables) | parseVariables != 1) + parseVariables = 1 // added for debugging + endif + + variable numLines, idx, numEntries, numMatches + string procText, reStart, name, StaticKeyword + + Wave/T helpWave = getHelpWave() + + // regexp: match case insensitive (?i) leading spaces don't matter. optional static statement. search for structure name which contains no spaces. followed by an optional space and nearly anything like inline comments + // help for regex on https://regex101.com/ + reStart = "^(?i)[[:space:]]*((?:static[[:space:]])?)[[:space:]]*structure[[:space:]]+([^[:space:]\/]+)[[:space:]\/]?.*" + Grep/Q/INDX/E=reStart text + Wave W_Index + Duplicate/FREE W_Index wavStructureStart + KillWaves/Z W_Index + KillStrings/Z S_fileName + WaveClear W_Index + if(!V_Value) // no matches + return 0 + endif + numMatches = DimSize(wavStructureStart, 0) + + // optionally analyze structure elements + if(parseVariables) + // regexp: match case insensitive endstructure followed by (space or /) and anything else or just a lineend + // does not match endstructure23 but endstructure// + Grep/Q/INDX/E="^(?i)[[:space:]]*(?:endstructure(?:[[:space:]]|\/).*)|endstructure$" text + Wave W_Index + Duplicate/FREE W_Index wavStructureEnd + KillWaves/Z W_Index + KillStrings/Z S_fileName + WaveClear W_Index + if(numMatches != DimSize(wavStructureEnd, 0)) + numMatches = 0 + return 0 + endif + endif + + numEntries = DimSize(declWave, 0) + Redimension/N=(numEntries + numMatches, -1) declWave, lineWave, helpWave + + for(idx = numEntries; idx < (numEntries + numMatches); idx +=1) + SplitString/E=reStart text[wavStructureStart[(idx - numEntries)]], StaticKeyword, name + declWave[idx][0] = createMarkerForType(LowerStr(StaticKeyword) + "structure") // no " " between static and structure needed + declWave[idx][1] = name + + // optionally parse structure elements + if(parseVariables) + Duplicate/FREE/R=[(wavStructureStart[(idx - numEntries)]),(wavStructureEnd[(idx - numEntries)])] text, temp + declWave[idx][1] += getStructureElements(temp) + WaveClear temp + endif + + lineWave[idx] = wavStructureStart[(idx - numEntries)] + endfor + + WaveClear wavStructureStart, wavStructureEnd +End + +/// @brief Return the text of the given procedure as free wave splitted at the EOL +static Function/WAVE getProcedureTextAsWave(module, procedureWithoutModule) + string module, procedureWithoutModule + + string procText + variable numLines + + // get procedure code + procText = getProcedureText("", 0, module, procedureWithoutModule) + +#if (IgorVersion() >= 7.0) + return ListToTextWave(procText, "\r") +#else + numLines = ItemsInList(procText, "\r") + + if(numLines == 0) + Make/FREE/N=(numLines)/T wv + return wv + endif + + Make/FREE/N=(numLines)/T wv = StringFromList(p, procText, "\r") + return wv +#endif +End + +// add basic html +Function/S AddHTML(context) + string context + + string line, html, re + string str0, str1, str2, str3, str4 + variable n, lines + + html = "" + lines = ItemsInList(context, "\r") + for(n = 0; n < lines; n += 1) + line = StringFromList(n, context, "\r") + re = "\s*([\/]{2,})\s?(.*)" + SplitString/E=(re) line, str0, str1 + if(V_flag != 2) + break + endif + line = str1 + if(strlen(str0) == 3) // Doxygen comments + re = "(?i)(.*@param(?:\[(?:in|out)\])?\s+)(\w+)(\s.*)" + SplitString/E=(re) line, str0, str1, str2 + if(V_flag == 3) + line = str0 + line += "" + str1 + " " + line += str2 + endif + re = "(?i)(.*)@(\w+)(\s.*)" + SplitString/E=(re) line, str0, str1, str2 + if(V_flag == 3) + line = str0 + line += "@" + str1 + "" + line += str2 + endif + endif + html += line + "
" + endfor + html = RemoveEnding(html, "
") + html = "" + html + "" + + return html +End + +// get code of procedure in module +// +// see `DisplayHelpTopic("ProcedureText")` +// +// @param funcName Name of Function. Leave blank to get full procedure text +// @param linesOfContext line numbers in addition to the function definition. Set to @c 0 to return only the function. +// set to @c -1 to return lines before the procedure that are not part of the preceding macro or function +// @param module independent module +// @param procedure procedure without module definition +// @return multi-line string with function definition +Function/S getProcedureText(funcName, linesOfContext, module, procedure) + string funcName, module, procedure + variable linesOfContext + + if(!isProcGlobal(module)) + debugPrint(procedure + " is not in ProcGlobal") + procedure = procedure + " [" + module + "]" + endif + + return ProcedureText(funcName, linesOfContext, procedure) +End + +// Returns a list of independent modules +// Includes ProcGlobal but skips all WM modules and the current module in release mode +Function/S getModuleList() + String moduleList + + moduleList = IndependentModuleList(";") + moduleList = ListMatch(moduleList, "!WM*", ";") // skip WM modules + moduleList = ListMatch(moduleList, "!RCP*", ";") // skip WM's Resize Controls modul + String module = GetIndependentModuleName() + + moduleList = "ProcGlobal;" + SortList(moduleList) + + return moduleList +End + +// get help wave: after parsing the function comment is stored here +// +// Return refrence to (text) Wave/T +Function/Wave getHelpWave() + DFREF dfr = createDFWithAllParents(pkgFolder) + WAVE/Z/T/SDFR=dfr wv = $helpWave + + if(!WaveExists(wv)) + Make/T/N=(128, 2) dfr:$helpWave/Wave=wv + endif + + return wv +End + +static Structure procedure + String id + Variable row + String name + String module + String fullName +Endstructure + +/// @brief compile all procedures +Function compile() + Execute/P/Z/Q "COMPILEPROCEDURES " +End diff --git a/samples/IGOR Pro/functions.ipf b/samples/IGOR Pro/functions.ipf index a1c823638f..b00d481ec8 100644 --- a/samples/IGOR Pro/functions.ipf +++ b/samples/IGOR Pro/functions.ipf @@ -28,7 +28,7 @@ Function CallOperationsAndBuiltInFuncs(string var) string someDQString = "abcd" - Make/N=(1,2,3,4) myWave + Make/N=(1,2,3,4) root:myWave/WAVE=myWave Redimension/N=(-1,-1,-1,5) myWave print strlen(someDQString) diff --git a/vendor/README.md b/vendor/README.md index 9eae7a2656..4465b69ff5 100644 --- a/vendor/README.md +++ b/vendor/README.md @@ -175,6 +175,7 @@ This is a list of grammars that Linguist selects to provide syntax highlighting - **HolyC:** [codingdandy/holyc.tmbundle](https://github.com/codingdandy/holyc.tmbundle) - **Hy:** [Slowki/hy.tmLanguage](https://github.com/Slowki/hy.tmLanguage) - **IDL:** [mgalloy/idl.tmbundle](https://github.com/mgalloy/idl.tmbundle) +- **IGOR Pro:** [byte-physics/language-igor](https://github.com/byte-physics/language-igor) - **INI:** [textmate/ini.tmbundle](https://github.com/textmate/ini.tmbundle) - **Idris:** [idris-hackers/idris-sublime](https://github.com/idris-hackers/idris-sublime) - **Ignore List:** [Alhadis/language-etc](https://github.com/Alhadis/language-etc) diff --git a/vendor/grammars/language-igor b/vendor/grammars/language-igor new file mode 160000 index 0000000000..dc7199d49d --- /dev/null +++ b/vendor/grammars/language-igor @@ -0,0 +1 @@ +Subproject commit dc7199d49d6294db12210d803282c18c7b73a5ed diff --git a/vendor/licenses/grammar/language-igor.txt b/vendor/licenses/grammar/language-igor.txt new file mode 100644 index 0000000000..546ece7402 --- /dev/null +++ b/vendor/licenses/grammar/language-igor.txt @@ -0,0 +1,38 @@ +--- +type: grammar +name: language-igor +version: 9bf5cad5d604db6c52f12619f8bcdbc1bf9872c6 +license: bsd-3-clause +--- +BSD 3-Clause License + +Copyright (c) 2012, User 741 +Copyright (c) 2017, Jeanine Adkisson, Matthias Kastner +Copyright (c) 2017, Thomas Braun +Copyright (c) 2019, () byte physics +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file