Symbol Highlighting
WinWrap® Basic is an embedded macro language component available for .NET and COM 32/64 bit Windows applications. The WinWrap® Basic Component is an alternative to Visual Basic for Applications (VBA), ActiveX (e.g. VBScript, JScript, PerlScript, Rexx-based WSH engines and others), and VSTA for this purpose. The WinWrap® Basic Component is compatible with VBA, Sax Basic, VB.NET and Visual Basic 6.0 style scripts.
Symbol Highlighting (v10.41+)
- Highlight all instances of symbol by clicking on it
- Navigate to other instances of the symbol with a scrollbar
- Navigate using Shift-Alt arrow hot-keys
Clicking on pv in line #13 highlights all the references to pv and its definition.
The definition has a rectangle outline around the highlight.
'#Language "WWB-COM"
Option Explicit
Module M1
Public pv As String
Friend fv As String
End Module
Sub Main
M1.pv = "hi"
Assert M1.pv, "hi"
pv = "bye"
Assert pv, "bye"
fv = "private"
Assert fv, "private"
End Sub
Sub Assert(ByVal e1 As Variant, ByVal e2 As Variant)
If e1 <> e2 Then Stop
End Sub
Navigation
In addition to highlighting the symbol, a scroll bar for rapidly selecting a symbol is displayed in the upper right.
API
To turn off symbol highlighting use
Query("Feature HighlightSymbol Off").
The sample code below uses the
SymbolInfo method
to list and navigate symbol information just like the IDE does.
public partial class Form1 : Form
{
private struct Position
{
public int start;
public int length;
}
private List<Position> idPositions = new List<Position>();
public Form1()
{
InitializeComponent();
}
private void basicIdeCtl1_Change(object sender, EventArgs e)
{
UpdateIds();
}
private void basicIdeCtl1_SelChange(object sender, EventArgs e)
{
if (radioButtonCurrentIdOnly.Checked)
UpdateCurrentIdOnly();
}
private void radioButtonAllIds_CheckedChanged(object sender, EventArgs e)
{
UpdateIds();
}
private void radioButtonCurrentIdOnly_CheckedChanged(object sender, EventArgs e)
{
UpdateIds();
}
private void listBoxIds_SelectedIndexChanged(object sender, EventArgs e)
{
Position position = idPositions[listBoxIds.SelectedIndex];
basicIdeCtl1.SelStart = position.start;
basicIdeCtl1.SelLength = position.length;
}
private void UpdateIds()
{
if (radioButtonAllIds.Checked)
UpdateAllIds();
else if (radioButtonCurrentIdOnly.Checked)
UpdateCurrentIdOnly();
}
private void UpdateAllIds()
{
idPositions.Clear();
listBoxIds.Items.Clear();
// get all ids for the current macro
string expr = @"{""expr"":""Global"",""all_ids"":true,""ids_only"":true}";
string jsonText = basicIdeCtl1.SymbolInfo("", expr, 0, false);
// sample jsonText:
// {"target":"F:\\Temp\\ww10\\m1.bas",
// "all_ids":[50,52,65,67,90,92,122,126,132,134,135,137,150,156,157,159,
// 160,162,174,176,190,196,197,199,212,214,232,238,239,241,
// 269,275,282,284,303,305,326,328,332,334]}
dynamic jsonObject = WinWrap.Basic.Util.ParseJson(jsonText);
int start = -1;
foreach (int index in jsonObject.all_ids)
{
// indexes alternate start, end, start, end, etc
if (start == -1)
start = index;
else
{
int length = index - start;
idPositions.Add(new Position { start = start, length = length });
int line = basicIdeCtl1.LineFromIndex(start);
int offset = start - basicIdeCtl1.IndexFromLine(line);
string id = basicIdeCtl1.Text.Substring(start, length);
listBoxIds.Items.Add($"{line}@{offset}:{length} {id}");
start = -1;
}
}
}
private void UpdateCurrentIdOnly()
{
idPositions.Clear();
listBoxIds.Items.Clear();
// get ids for the current macro at the caret location
string expr = @"{""ids"":true,""ids_only"":true}";
string jsonText = basicIdeCtl1.SymbolInfo("", expr, -1, false);
// sample jsonText:
// {"target":"F:\\Temp\\ww10\\m1.bas",
// "ids":
// {"pv":
// {"defs":[65],
// "refs":[135,160,174,197]}}}
dynamic jsonObject = WinWrap.Basic.Util.ParseJson(jsonText);
dynamic idsObject = jsonObject.ids;
if ((bool)idsObject)
{
// ids json object exists, get the member names
string[] ids = idsObject[""];
foreach (string id in ids)
{
// caret is on a symbol
int length = id.Length;
dynamic indexesObject = idsObject[id];
foreach (string member in new string[] { "defs", "refs" })
{
foreach (int start in indexesObject[member])
{
idPositions.Add(new Position { start = start, length = length });
int line = basicIdeCtl1.LineFromIndex(start);
int offset = start - basicIdeCtl1.IndexFromLine(line);
listBoxIds.Items.Add($"{member.Substring(0, 3)}: {line}@{offset}:{length} {id}");
}
}
}
}
}
}
Conclusion
Rapidly locate all instances of a symbol in a script and navigate to the definition, next or previous reference.
Copyright Polar Engineering, Inc.