Skip to content
pb-diff Help

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.

pb-diff comparing two versions of the PowerBuilder window w_order_entry. The hierarchy tree on the left, with Only Changed Items on as every comparison opens, lists the changed variables, prototypes, functions and the cb_save control with their change markers, and the function wf_total is selected. The Old and New panes show that function side by side: green added lines that reject an out-of-range discount and skip cancelled order lines, a red deleted debug message line, and yellow modified lines where Truncate becomes Round and the total display moves to a new function.
Two versions of the w_order_entry window compared structurally. The hierarchy on the left opens on the changed items only, and the selected function wf_total is shown Old beside New, with its added, deleted and modified lines marked. Select the image to view it at full size.

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:

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.