File Compare
A File Compare tab is where you read one pair of files in detail: what the object is made of, which of its parts changed, and exactly which characters inside a line are different. One opens from New Comparison, by drilling into a modified row of a Compare Summary, or from the command line. Your first comparison walks through one.
The layout
The hierarchy tree occupies the left of the tab. It holds the parsed
structure of the object: the export header, forward declarations, type
and property blocks, structures, variable blocks, external function
declarations, one node per function and per event, each control with its
own property block and scripts, and the .create and
.destroy scripts. Only sections that exist in at least one
of the two files appear, so an object with no instance variables has no
Instance Variables node.
Selecting a node shows that section's compare on the right: the Old text and the New text side by side, aligned, with changed lines highlighted and the language's syntax colouring applied. The two sides are one drawn surface rather than two controls locked together, so they share a scroll position by construction and can never drift apart.
The two sides open at equal widths. To give one of them more room, drag the line between them: the pointer becomes a resize arrow over it, in the column headers as in the text, and each side keeps at least its line numbers and eight characters. The rows stay aligned and still scroll as one, and the horizontal scroll bar reaches the end of the longest line in the narrower side. Double-click the line, or choose View ▸ Equal Column Widths, to put the sides back to equal widths. From the keyboard, Ctrl+Shift+← and Ctrl+Shift+→ move the line beside the side the caret is in. Each tab keeps its own proportion while it is open, and a new File Compare opens with the proportion the last one was left at.
At every level the panes show decoded source rather than text regenerated from the parser model. Selecting a function, event, control, XML element or other content node shows its exact source. Selecting a structural parent shows all source fragments below it in their physical order, and selecting the root shows the complete file, including unchanged sections and blank lines. PowerScript continuation lines, JavaScript top-level fragments and raw XML subtrees therefore remain exactly recognisable. This rule also applies to the two comparisons in a three-way merge.
A DataWindow adds one level below each statement: every direct property is selectable on its own. The tree distinguishes Database Columns inside Data Source (Table) from the visual Column controls inside a band's Controls group. Selecting a control shows all of its properties, selecting a section shows everything below that section, and selecting the DataWindow root shows the complete object. A property keeps its original spelling and spacing, and a parent uses the real exact source slices in its scope. This keeps separate statements distinct even when PowerBuilder writes them on one physical line. Only the explicitly derived DataWindow Overview is not source text.
Each tree node carries a status marker, and a node's marker
aggregates its children: a control whose clicked event
changed is itself shown as modified. See the Status Icon Legend.
The tab itself holds no commands. What a File Compare can do it adds to the application's tool bar, after the commands that are always there, in this order: Copy as Unified Diff; the two merge arrows, Take Old Version and Take New Version; Save, for what they merged; the two filters; the four change-navigation buttons; the search box. All of it is on the menus as well.
The change minimap
The strip down the right edge of the compare, where a scroll bar would be, is a map of the whole object drawn at once. Every change is a mark, in one of three lanes: deletions on the left of the strip, modifications in the middle, additions on the right. The part of the object currently on screen is banded. Click or drag on the strip to go there.
It answers a question a pair of counters cannot: seventeen changes bunched into one function and seventeen scattered over a thousand lines are the same numbers and completely different jobs. Four marks in one band means one function was rewritten; forty marks spread evenly means a mechanical change, such as a rename, a re-indent or an attribute case change, and probably an option to switch on rather than an afternoon of reading. View ▸ Minimap hides it and brings it back.
Only Changed Items and Only Changed Lines
Two independent toggles, on the View menu and as the tick boxes Changed Items and Changed Lines in the tool bar:
- Only Changed Items (Ctrl+Shift+I) hides unchanged nodes from the tree, so only what changed is left, with the nodes above it. It is on when a comparison opens; clear it to see the whole object. Two files with nothing changed keep their whole tree, and the status bar says the two sides are identical. Where every new tab starts is Show only changed items when a comparison opens , in Options.
- Only Changed Lines (Ctrl+Shift+L) collapses runs of unchanged lines inside the selected scope, so a three-line change in a 300-line function or a few changed properties in a DataWindow fill the pane instead of hiding in it. A couple of lines of context are kept either side of every change. It is off when a comparison opens.
A folded run is replaced by a placeholder saying how many lines it hides. Click the placeholder to unfold that run, or move onto it with ↑ and ↓ and press Enter or Space. There is no preview on hover: a run opens because you asked it to, and stays open until the next item is selected. Folding only changes how you read the result. The compare, the merge and the reports are the same whether the text is folded or not.
Turning both on and walking with Alt+↓ is the quickest way through a large compare: a window with 60 sections and 4 changes becomes 4 nodes, and each changed script shows a few lines of context instead of hundreds.
Moving through the changes
The four navigation commands are on the Navigate menu, and in the tool bar as First, Previous, Next and Last. They step through every change within the current script and then continue into the next changed item in the tree, so holding the Next key takes you through the whole object in reading order.
| Command | Shortcut |
|---|---|
| First Change | Alt+← |
| Previous Change | Alt+↑ |
| Next Change | Alt+↓ |
| Last Change | Alt+→ |
The status bar carries the counts of what changed, and at its right-hand end two positions: Changed item 4 of 17 , the fourth changed item of the seventeen this compare found, and beside it Change 2 of 6 , where you are among the changes inside the item on show. Both are there at once because they answer different questions. Stepping through a long script moves the second and leaves the first where it is. Changed item 1 of 1 means the whole file has one changed item, so if that change looks trivial the whole difference is trivial; Change 1 of 1 says nothing about the rest of the file.
Finding text
The search box at the end of the tool bar searches the item on show, not the whole object, which is what its tool tip means by Find in this item. A hit in a script you are not looking at would move the tree, the pane and the caret all at once, so the search is confined to the item you are reading.
Type into the box and press Enter to go to the first match. F3, or Edit ▸ Find Next, goes to the next one, and the search wraps round the end of the item rather than stopping there. Edit ▸ Find (Ctrl+F) puts the keyboard in the box from wherever you were, and finds the box belonging to whichever tab is in front. Matching ignores case. The status bar reports the line a match was found on, or says the text is not in this item.
Changes inside a line
When a line was modified rather than replaced, pb-diff also highlights the part of it that changed, token by token (whole tokens of the current language). Two options adjust this: Underline and strike through in-line changes adds underline and strikethrough on top of the colouring, and Full modified line compare in the detailed display switches the highlighting to individual characters on every modified line, at some cost in visual noise.
Lines that are too dissimilar to be a plausible edit of one another are deliberately not paired: they are reported as a deletion plus an addition. The Resync distance threshold option decides where that line falls.
When a change comes down to one operator, one argument or one
attribute, such as > against >=,
Navigate ▸ Compare Current Line
(Ctrl+L) sends the current line pair to a Line Compare tab, which stacks the two
lines and aligns their matching segments so the difference has nowhere
to hide.
Indentation
PowerBuilder indents with tabs. The compare panes lay a tab out to the next stop, exactly as PowerBuilder's own source editor does, so a script written in the IDE reads here the way it reads there. How far a stop is comes from Options ▸ Text settings and its Tab size (columns): box, whose default of 3 is PowerBuilder's own. If indentation does not line up the way you expect, that is the setting to match to your IDE.
It changes only what is drawn. The comparison is made on the text as the file holds it, and text copied out of a pane carries the tabs the author wrote rather than the spaces shown for them.
Differences that are artefacts rather than edits, such as re-indentation or DataWindow attribute case after an upgrade, are taken out by options rather than read one by one; see Take the noise out.
The signature strip
Below the compare panes is a strip showing the old and the new signature (or header) of the selected item. It is where to look when a function shows as modified but its body looks identical: the change is in the parameter list or the return type. It appears for items that have a declaration, such as functions and events, and not for groups and controls, whose only header is their name. View ▸ Signatures shows and hides it. A three-way merge shows the same strip, with one line for each of File1, the Base and File2.
Copying, and the right-click menus
Text in either pane can be selected with the mouse and copied with
Ctrl+C. A selection belongs to one side, so what
you copy is one version's text and not the two interleaved. Edit
▸ Copy as Unified Diff, also the first button this tab puts in
the tool bar, puts the whole compare on the clipboard as a standard
patch instead, which is what a review comment or a ticket wants.
pb-diff-cli compare old.srw new.srw --format json is the
structured result for another tool.
Both halves of the tab carry a context menu, so the commands you reach for most often are where your hand already is. Everything on them is also on the menu bar, with the same shortcut:
| Right-click on | What you get |
|---|---|
| A compare pane | Copy, Copy as Unified Diff, Compare Current Line, Previous Change, Next Change. |
| The hierarchy tree | Only Changed Items, Only Changed Lines, First Change, Last Change, Refresh. |
The two filters carry a tick when they are on. Apart from these, only the action rows of a three-way merge have a right-click menu (Take from Left, Keep Base, Take from Right); everywhere else the commands are on the menu bar and the tool bar.
Reports
Three reports come from this tab, under Compare ▸ Reports: Full File Report, File Changes Report and Current Script Report. Current Script is enabled after you select a source item; a root, structural group or derived node is not a script. Each opens as its own tab; see Reports.
Merging
A File Compare shows the differences and lets you carry them across. Old is the reference and the result starts as New, so before you decide anything File ▸ Save writes the new version's content back out character for character. Compare ▸ Merge ▸ Take Old Version, and its arrow in the tool bar, moves one element back towards the old version: it restores something New dropped, removes something New added, or reverts something New changed. Take New Version abandons that decision.
Select a tree node to act on a whole item: a function, event, variable block, control, group or the whole object. To act only on a changed block, put the caret on one of its lines by clicking it or stepping to it with the change navigation; if the caret is on a line both versions share, the command applies to the whole item. The Merge target line above the merge panel says what the next operation targets, so you can check it before running it.
The merge panel under the compare holds the merged text of the current element and lists anything pb-diff finds that would stop the merged object from compiling. It opens on the first operation, and View ▸ Merge Panel shows and hides it. You can edit the text of an element that has lines of its own; a control, a group or the object itself contains other elements instead, so its box is read-only. Edit ▸ Undo and Edit ▸ Redo act on the script you are viewing.
An individual DataWindow property is a reading aid rather than an
independently writable source fragment, so the merge commands are
disabled on a property leaf. Select its owning control, band, database
column or Table section to merge the complete statement. This keeps the
surrounding parentheses and adjacent properties together and preserves
an importable .srd.
Save, in the tool bar or as File ▸
Save, writes the result as an export file; nothing is written
into a .pbl. How merging works
describes what a merge writes, the markers it leaves, and the four
places a control lives; Your first
two-way merge does it on the examples. Where you have the version
both sides started from, a three-way
merge can tell your change from theirs, and this cannot.
When the file will not parse
A corrupt DataWindow, a truncated export or an XML file with a broken tag falls back to a plain text compare rather than failing. If a compare suddenly shows a flat list of lines instead of the usual hierarchy, that is what happened. Check the file itself before reading the differences; see Troubleshooting.
Re-running the comparison
Compare ▸ Refresh (F5) reads both files again and compares them again, which is what you want after editing one of them elsewhere or after changing an option. It starts a merge session holding no decisions, so it asks first if the one you have is unsaved.