diff --git a/core/language/en-GB/SearchVariables.multids b/core/language/en-GB/SearchVariables.multids new file mode 100644 index 000000000..014188fb6 --- /dev/null +++ b/core/language/en-GB/SearchVariables.multids @@ -0,0 +1,30 @@ +title: $:/language/Search/Variables/ + +Caption: Variables +Content: Variable content +Clear/Exclude: Clear exlude +Clear/Search: Clear search +Exclude: Exclude: +Exclude/Edit: Edit +Function/Content: Function definition +Function/Definition: Function definition +Exclude/Hide: Hide exclude input +Exclude/Hint: Exclude Filter eg: [prefix[.]] +Exclude/Save: Create new exclude filter +Exclude/Show: Show exclude input +Exclude/Show/Config: Show saved exclude configurations +Exclude/Description: EDIT ME - Description is shown in the dropdown +ExpandAll: Expand all: +FoldAll: Fold all: +Filter: Search: +Filter/Hint: Search Variable Name eg: .attr +Hint: Filter global variables +Info/Reset: Reset details search input +Info/Toggle/Show: Show details search input +Info/Toggle/Hide: Hide details search input +Matches: //<> matches// +Search: Search Variables +Search/Details: Search tiddler text, tags: +Signature: Variable signature +Option/Type: Type: +Option/Sort: Sort: \ No newline at end of file diff --git a/core/language/en-GB/Snippets/variables-prefix-dot.tid b/core/language/en-GB/Snippets/variables-prefix-dot.tid new file mode 100644 index 000000000..7681bf182 --- /dev/null +++ b/core/language/en-GB/Snippets/variables-prefix-dot.tid @@ -0,0 +1,5 @@ +description: [prefix[.]] Documentation variables prefixed with a dot +tags: $:/tags/Variables/Exclude/Snippet +title: $:/variables/exclude/prefix-dot + +[prefix[.]] \ No newline at end of file diff --git a/core/modules/filters/format/variable.js b/core/modules/filters/format/variable.js new file mode 100644 index 000000000..ab23154a0 --- /dev/null +++ b/core/modules/filters/format/variable.js @@ -0,0 +1,33 @@ +/*\ +title: $:/core/modules/filters/format/variable.js +type: application/javascript +module-type: formatfilteroperator +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Export our filter function +*/ +exports.variable = function(source,operand,options) { + var results = [], + widget = options.widget, + variable, + varInfo, + variableTemplate = (operand.length >=6 && operand) ? operand : "$type$ $name$($params$) $firstLine$"; + + source(function(tiddler,title) { + varInfo = widget.getVariableInfo(title, {}); + varInfo.name = title; + if(title && title.length) { + variable = $tw.utils.formatVariableString(variableTemplate, varInfo); + results.push(variable); + } + }); + return results; +}; + +})(); diff --git a/core/modules/filters/jsonvariables.js b/core/modules/filters/jsonvariables.js new file mode 100644 index 000000000..cb5e1a575 --- /dev/null +++ b/core/modules/filters/jsonvariables.js @@ -0,0 +1,33 @@ +/*\ +title: $:/core/modules/filters/jsonvariable.js +type: application/javascript +module-type: filteroperator + +Filter operator to get widget variable info and +Display as JSON with basic formatting + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Export our filter function +*/ +exports.jsonvariable = function(source,operator,options) { + var results = [], + widget = options.widget; + // "replacer" must be defined, otherwise JSON.stringify will throw a circular reference error RSOD + // "replacer" does not contain: isCacheable + var replacer= "params name value default resultList srcVariable text isFunctionDefinition isProcedureDefinition isWidgetDefinition isMacroDefinition".split(" "); + source(function(tiddler,title) { + var variable = widget.getVariableInfo(title, {}), + text = JSON.stringify(variable,replacer); + results.push(text || ""); + }); + return results; +}; + +})(); diff --git a/core/modules/filters/variables-wl.js b/core/modules/filters/variables-wl.js new file mode 100644 index 000000000..3c3076e80 --- /dev/null +++ b/core/modules/filters/variables-wl.js @@ -0,0 +1,73 @@ +/*\ +title: $:/core/modules/filters/variables-wl.js +type: application/javascript +module-type: filteroperator + +Filter operator for returning the names of the active variables + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Export our filter function +*/ +exports["variables-wl"] = function(source,operator,options) { + var operands = []; + $tw.utils.each(operator.operands,function(operand,index){ + operands.push({ + name: (index + 1).toString(), + value: operand + }); + }); + var names = [], + sort, + widget = options.widget, + included = (operands[0].value) ? operands[0].value : "var fn proc macro widget"; + // all will overwrite + included = ((included.indexOf("all") !== -1)) ? "var fn proc macro widget" : included; + + // variableTemplate = (operands.length > 1 && operands[1]) ? operands[1].value : "$type$ $name$($params$) $firstLine$"; + + switch(operator.suffix) { + case "raw": + sort = false; + break; + case "alphabetical": // the fallthrough is intentional. "alphabetical" is default + default: + sort = true; + break; + } + while(widget && !widget.hasOwnProperty("variables")) { + widget = widget.parentWidget; + } + if(widget && widget.variables) { + for(var variable in widget.variables) { + var varInfo = widget.getVariableInfo(variable, {}); + + // varInfo.name = variable; + // variable = $tw.utils.formatVariableString(variableTemplate, varInfo); + + if( ((included.indexOf("fn") !== -1) && varInfo.srcVariable.isFunctionDefinition ) || + ((included.indexOf("proc") !== -1) && varInfo.srcVariable.isProcedureDefinition ) || + ((included.indexOf("macro") !== -1) && varInfo.srcVariable.isMacroDefinition ) || + ((included.indexOf("widget") !== -1) && varInfo.srcVariable.isWidgetDefinition ) ) + { + names.push(variable); + } else if((included.indexOf("var") !== -1) && !varInfo.srcVariable.isFunctionDefinition && !varInfo.srcVariable.isProcedureDefinition && !varInfo.srcVariable.isMacroDefinition && !varInfo.srcVariable.isWidgetDefinition ) + { + names.push(variable); + } + } + } + if(sort) { + return names.sort(); + } else { + return names; + } +}; + +})(); diff --git a/core/modules/utils/utils-format.js b/core/modules/utils/utils-format.js new file mode 100644 index 000000000..926ebc834 --- /dev/null +++ b/core/modules/utils/utils-format.js @@ -0,0 +1,71 @@ +/*\ +title: $:/core/modules/utils/utils-format.js +type: application/javascript +module-type: utils + +Various static utility functions. + +\*/ +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.formatVariableString = function(template,options) { + var result = "", + firstLine = "", + name = options.name || "", + params = options.params || "", + os = options.srcVariable || options.name; + var type = (os.isFunctionDefinition) ? "\\\\function" : (os.isMacroDefinition) ? "\\\\define" : + (os.isProcedureDefinition) ? "\\\\procedure" : (os.isWidgetDefinition) ? "\\\\widget" : "", + varType = (os.isFunctionDefinition) ? "fn" : (os.isMacroDefinition) ? "macro" : + (os.isProcedureDefinition) ? "proc" : (os.isWidgetDefinition) ? "widget" : "var"; + var t = (!os.isFunctionDefinition && !os.isMacroDefinition && !os.isProcedureDefinition && !os.isWidgetDefinition) ? "$name$" : template; + var matches = [ + [/^\$type\$/i, function() { + return (type) ? type : ""; + }], + [/^\$name\$/i, function() { + return name; + }], + [/^\$params\$/i, function() { + var elements = [], + paramString = ""; + if(params && params[0] && params[0].name) { + $tw.utils.each(params, function(p) { + elements.push(p.name + ((p.default) ? ':"' + p.default + '"' : "")); + }); + paramString = elements.join(", "); + } + // return (type) ? "(" + paramString + ")" : ""; + return (type) ? paramString : ""; + }], + [/^\$firstLine\$/i, function() { + var lines = os.value.split("\n"), + suffix = (lines.length > 1) ? "..." : ""; + return (os.isFunctionDefinition) ? lines[0].replace("\\", "\\\\") + suffix: ""; + }], + [/^\$varType\$/i, function() { + return varType; + }] + ]; + while(t.length){ + var matchString = ""; + $tw.utils.each(matches, function(m) { + var match = m[0].exec(t); + if(match) { + matchString = m[1].call(null,match); + t = t.substr(match[0].length); + return false; + } + }); + if(matchString) { + result += matchString; + } else { + result += t.charAt(0); + t = t.substr(1); + } + } + result = result.replace(/\\(.)/g,"$1"); + return result.trim(); +}; diff --git a/core/ui/AdvancedSearch/Variables.tid b/core/ui/AdvancedSearch/Variables.tid new file mode 100644 index 000000000..55053c886 --- /dev/null +++ b/core/ui/AdvancedSearch/Variables.tid @@ -0,0 +1,27 @@ +caption: {{$:/language/Search/Variables/Caption}} +created: 20240215233810357 +list-before: $:/core/ui/AdvancedSearch/Filter +modified: 20240429173634149 +tags: $:/tags/AdvancedSearch +title: $:/core/ui/AdvancedSearch/Variables +type: text/vnd.tiddlywiki + +\define set-next-input-tab(beforeafter:"after") + +<$macrocall $name="change-input-tab" + stateTitle="$:/state/tab--1498284803" + tag="$:/tags/AdvancedSearch" + beforeafter="$beforeafter$" + defaultState="$:/core/ui/AdvancedSearch/System" + actions="<$action-setfield $tiddler='$:/state/advancedsearch/currentTab' text=<>/>"/> +\end + +{{$:/language/Search/Variables/Hint}} + + \ No newline at end of file diff --git a/core/ui/AdvancedSearch/Variables_ItemTemplate.tid b/core/ui/AdvancedSearch/Variables_ItemTemplate.tid new file mode 100644 index 000000000..840d6ee22 --- /dev/null +++ b/core/ui/AdvancedSearch/Variables_ItemTemplate.tid @@ -0,0 +1,16 @@ +title: $:/core/ui/AdvancedSearch/Variables/ItemTemplate + +\whitespace trim + +\procedure editSnippet() +<$action-sendmessage $message="tm-edit-tiddler" title=<> /> +\end + +<$link to={{!!text}} > + <$let tv-wikilinks="no"> + <$transclude field="description"/> + + +<$button actions=<> class="tc-btn-invisible tc-small-gap-left" tooltip={{$:/language/Search/Variables/Exclude/Edit}}> + {{$:/core/images/edit-button}} + diff --git a/core/wiki/macros/search-variables.tid b/core/wiki/macros/search-variables.tid new file mode 100644 index 000000000..c1c10943c --- /dev/null +++ b/core/wiki/macros/search-variables.tid @@ -0,0 +1,464 @@ +title: $:/core/macros/search-variables +tags: $:/tags/Global + +\whitespace trim + +\procedure lingo-base() $:/language/Search/Variables/ + + +\procedure DV-VAR-FILTER-OPTIONS() all fn var proc macro widget +\procedure DV-FILTER-OPTIONS() $:/temp/varSearch/options +\procedure DV-SORT-OPTIONS() $:/temp/varSearch/sort + + +\procedure DV-RAW-FILTER-STR() [variables:raw<_wlf.dv-type>] +\procedure DV-FILTER-STR() [variables<_wlf.dv-type>] + + +\procedure DV-FOLDED() $:/temp/varFolded +\procedure DV-SEARCH() $:/temp/varSearch +\procedure DV-SEARCH-DETAILS() $:/temp/varSearch/details +\procedure DV-SEARCH-STATE() $:/state/varSearch/name +\procedure DV-EXCLUDE() $:/state/varExclude + + +\procedure DV-TYPE-CONFIG() $:/config/DumpVariables/type-selector + + +\function wlf.dv-filterString() [<_wlf.dv-sort>match[raw]thenelse] +\function wlf.dv-formattedVar() [format:variable<_wlf.dv-varFormatStr>] + +\function wlf.dv-foldedState() [] [] +[join[/]] + + + + +\procedure wl-dumpvariables(type sort subfilter:"[[]]" format) + + + \function _wlf.dv-varFormatStr() [!is[blank]thenelse[$type$ $name$($params$)]] + \function _wlf.dv-type() [] + \function _wlf.dv-sort() [] + +

+ <$text text=`${ [subfilter] + +[filter] + +[count[]] }$` + /> + <> + <% if [split[]count[]compare::gt[4]] %> + <$text text=`subfilter: $(subfilter)$`/> + <%endif%> +

+ +
    + <$list filter="[subfilter] +[filter]" variable="varname"> +
  • + <$text text=<>/>
    + <% if [prefix[\function]] %> +
    <$text text={{{ [jsonvariable[]jsonextract[srcVariable],[value]] }}}/>
    + <% endif %> +
    <$text text={{{ [getvariable[]] }}}/>
    +
  • + +
+\end + + +\procedure dv-toggleState() +<$action-setfield $tiddler=<> text={{{ [get[text]] +[toggle[yes],[no]] }}}/> +<> +\end + +\procedure dv-toggleInfoState() +<$action-setfield $tiddler=<> + text={{{ [get[text]] +[toggle[yes],[no]] }}} +/> + + +<$action-setfield $tiddler=<> + text={{{ [!is[blank]then] :else[format:variable[$type$ $name$]] }}} +/> +\end + +\procedure dv-setDetailsSearchText() + + +<$action-setfield $tiddler=<> + text={{{ [format:variable[$type$ $name$]] }}} +/> +\end + +\procedure dv-clearStatesButton() +<> +<$button class="tc-btn-invisible tc-tiny-gap-left" tooltip={{$:/language/Search/Variables/FoldAll}}> + + <$action-deletetiddler $filter="[prefix]"/> + {{$:/core/images/fold-all-button}} + +\end + +\procedure dv-clearSearchButton() +<$button class="tc-btn-invisible btn-x" tooltip={{$:/language/Search/Variables/Clear/Search}}> + <$action-deletetiddler $tiddler=<>/> + <$action-sendmessage $message="tm-focus-selector" $param="input.x-inp"/> + {{$:/core/images/close-button}} + +\end + +\procedure dv-clearExcludeButton() +<$button class="tc-btn-invisible btn-yy" tooltip={{$:/language/Search/Variables/Clear/Exclude}}> + <$action-deletetiddler $tiddler=<>/> + <$action-sendmessage $message="tm-focus-selector" $param="input.y-inp"/> + {{$:/core/images/close-button}} + +\end + +\procedure dv-expandAllStatesButton() +<> +<$button class="tc-btn-invisible" tooltip={{$:/language/Search/Variables/ExpandAll}}> + <$action-setfield $tiddler=<> + text={{{ [get[text]] +[toggle[yes],[no]] }}} + /> + + <$list filter="[subfilter] +[search::some] +[filter]" + variable="varname" + > + <$action-setfield $tiddler=<> text="yes"/> + + {{$:/core/images/unfold-all-button}} + +\end + +\procedure dv-info() +
+ <$list filter="[all[tiddlers+shadows]] :filter[search:text,tags:words] + -[[$:/config/OriginalTiddlerPaths]] + -[[$:/HistoryList]] + -[[$:/StoryList]] + -[[$:/core]] + :filter[!type[application/javascript]] + :filter[!prefix[$:/temp/]] + :filter[!prefix[$:/state/]] + :filter[!plugin-type[plugin]]" + > + <$link class="tc-small-gap-left"/>
+ +
+\end + +\function wlf.dv-tmpTypeOptions() [] [] +[join[/]] +\function wlf.dv-tmpSortOptions() [] [] +[join[/]] + +\function wlf.dv-searchText() [] [] +[join[/]] +\function wlf.dv-getSearchText() [get[text]] + +\function wlf.dv-excludeText() [] [] +[join[/]] +\function wlf.dv-getExcludeText() [get[text]] + +\function wlf.dv-detailsSearch() [] [] [] +[join[/]] +\function wlf.dv-getDetailsSearchText() [get[text]] + +\function wlf.dv-varState() [] [] [] +[join[/]] +\function wlf.dv-toggleInfoState() [] [] +[join[/]] + + + + +\procedure search-variables(type sort subfilter:"[[]]" format) + + + \function _wlf.dv-varFormatStr() [!is[blank]thenelse[$type$ $name$($params$)]] + \function _wlf.dv-type() [!is[blank]then] :else[get[text]] + \function _wlf.dv-sort() [!is[blank]then] :else[get[text]] :else[[alphabetical]] + + <> + +

+ <$text text=`${ [subfilter] + +[search::some] + +[filter] + +[!filter] + +[count[]] }$` + /> + <> + <% if [split[]count[]compare::gt[4]] %> + <$text text=`subfilter: $(subfilter)$`/> + <%endif%> +

+ +
+ <$list filter="[subfilter] + +[search::some] + +[filter] + +[!filter]" + variable="varname" + > +
+ <$button actions=<> class="tc-small-gap-left tc-btn-invisible"> + <% if [get[text]match[yes]] %> + {{$:/core/images/down-arrow}} + <% else %> + {{$:/core/images/right-arrow}} + <% endif %> + <$text text=<>/> + + <% if [prefix[\function]] %> + + + <$text text={{{ [format:variable[$firstLine$]] }}}/> + + <% endif %> + + <% if [get[text]match[yes]] %> + <$button actions=<> + class="tc-btn-details tc-btn-invisible tc-small-gap-left" + > + <% if [get[text]match[yes]] %> + {{$:/core/images/up-arrow}} + <% else %> + {{$:/core/images/advanced-search-button}} + <% endif %> + +
+ <% if [get[text]match[yes]] %> +
+ <> + <$edit-text tiddler=<> tag=input class="wltc-fluid-input tc-small-gap-left"/> + <$button actions=<> + class="tc-btn-invisible tc-tiny-gap-left" + tooltip={{$:/language/Search/Variables/Info/Reset}} + > + {{$:/core/images/refresh-button}} + +
+ <> + <% endif %> + <% if [prefix[\function]] %> + <$codeblock code={{{ [jsonvariable[]jsonextract[srcVariable],[value]] }}}/> + <% endif %> +
<$text text={{{ [getvariable[]] }}}/>
+
+ <% endif %> +
+ +
+\end + + + + + + +\procedure dv-search-input-box() +<$text text={{$:/language/Search/Variables/Filter}}/> +<$edit-text tiddler=<> + tag=input + class="txt-input x-inp" + placeholder={{$:/language/Search/Variables/Filter/Hint}} + focus="yes" +/> +<> +\end + +\procedure dv-exclude-input-box() +<$text text={{$:/language/Search/Variables/Exclude}}/> +<$edit-text tiddler=<> + tag=input + class="txt-input y-inp" + placeholder={{$:/language/Search/Variables/Exclude/Hint}} +/> +<> +<% if [!is[blank]] %> + <> +<% endif %> +\end + +\function wlf.dv-opt-class() "c" [