Environment: VisualStudio 6.0
The EPM text editor under OS/2 provided a macro facility not unlike that in DevStudio,
which meant that before it had been around for long, a number of really useful macros
started popping up on internet sites that catered to OS/2 users. One particular set of
macros that I have really been missing since moving off of that platform is called
“Fenceposts” (though I am not entirely sure that was the original name). The family of
DevStudio macros presented here, duplicates this feature.
So what’s a fencepost?
A fencepost contains a filename and cursor position (row and column coordinates) within
the active document of your current DevStudio project. That is, it completely
describes a location within your sourcecode. Fenceposts can be planted, and they can
be pulled. Planting a fencepost saves this location information within the fencepost
stack. Pulling a fencepost then returns the editor to the most recently planted
fencepost, activating and opening documents as necessary, and removes that information
from the stack.
I find this kind of sourcecode navigation very useful, especially in a deeply nested
class hierarchy.
'------------------------------------------------------------------------------ 'FILE DESCRIPTION: Provide a stack for storing edit locations ' 'NOTES: '* Access to the postfile is very rudimentary -- the file is ' read completely, modified and rewritten when posts are ' added or removed. There is probably a better way, but that ' was the first method I found. '* I would like to add a 'Beep' when PullFencepost has nothing ' to do, but DevStudio provides no way to do this that I know ' of. '------------------------------------------------------------------------------ Sub SetDefaultFencepostKeyBindings() 'DESCRIPTION: Setup default key mappings for fencepost macros. 'This is simply an installation routine AddKeyBinding "Ctrl+Shift+NumPad Clear", "ClearFencepostStack", "Text" AddKeyBinding "Ctrl+Shift+Down Arrow", "PlantFencepost", "Text" AddKeyBinding "Ctrl+Shift+Up Arrow", "PullFencepost", "Text" End Sub Function postfilePathname() 'DESCRIPTION: File where fenceposts are stored. 'The postfile lives in the ActiveProject directory, so the 'pathname is built from that. str = Application.ActiveProject.FullName pos = InStrRev(str, "") str = Left(str, pos) postfilePathname = str + "_postfile.dat" End Function Sub PlantFencepost() 'DESCRIPTION: Save current location on an in-file stack for later. 'Access the filesystem Set fso = CreateObject("Scripting.FileSystemObject") fencepostfile = postfilePathname() 'If postfile exists, read into block If (fso.fileexists(fencepostfile)) Then Set f = fso.GetFile(fencepostfile) Set a = f.OpenAsTextStream(1) If f.Size > 0 Then block = a.readall End If a.Close End If 'Build Fencepost fencepost = ActiveDocument.FullName _ + "(" + CStr(ActiveDocument.Selection.CurrentLine) _ + ":" + CStr(ActiveDocument.Selection.CurrentColumn) _ + ")" 'Prepend fencepost to fencepost block block = fencepost + vbNewLine + block 'Write the block to file Set a = fso.CreateTextFile(fencepostfile, True) a.write (block) a.Close End Sub Sub PullFencepost() 'DESCRIPTION: Retrieve a previous location from the in-file stack. 'Access the filesystem Set fso = CreateObject("Scripting.FileSystemObject") fencepostfile = postfilePathname() 'If the file exists... If (fso.fileexists(fencepostfile)) Then Set f = fso.GetFile(fencepostfile) Set a = f.OpenAsTextStream(1) '...and if there are records to read If f.Size > 0 Then 'Read the file block = a.readall pos = InStr(block, vbNewLine) Line = Left(block, pos) block = Mid(block, pos + 2) a.Close 'Write the modified fencepost block Set a = fso.CreateTextFile(fencepostfile, True) a.write (block) a.Close 'If there is anything in the line If Len(Line) > 0 Then 'Parse the line into something like: 'fname(lineNum,ColNum) pos = InStr(Line, "(") fname = Left(Line, pos - 1) Line = Mid(Line, pos + 1) pos = InStr(Line, ":") lineNum = CInt(Left(Line, pos - 1)) Line = Mid(Line, pos + 1) pos = InStr(Line, ")") colNum = CInt(Left(Line, pos - 1)) 'Open or surface the given document Set doc = Documents.open(fname) 'Move to the proper location doc.Selection.moveTo lineNum,colNum 'moving the cursor around gives us some 'context around our post location doc.Selection.lineDown dsMove,3 doc.Selection.lineUp dsMove,6 'Move to the proper location again doc.Selection.moveTo lineNum,colNum End If End If End If End Sub Sub ClearFencepostStack() 'DESCRIPTION: Remove all entries from the fencepost stack Set fso = CreateObject("Scripting.FileSystemObject") fencepostfile = postfilePathname() Set a = fso.CreateTextFile(fencepostfile, True) a.Close MsgBox "Fenceposts cleared" End Sub