Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge branch 'master' into tablelist |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | table-list |
Files: | files | file ages | folders |
SHA1: |
93bf0308fcef3b2f683658856d31da39 |
User & Date: | peter.spjuth@gmail.com 2011-05-03 21:37:47.000 |
Context
2011-05-03
| ||
22:35 | Use images from tablelist check-in: 133c0fd5bc user: peter.spjuth@gmail.com tags: table-list | |
21:37 | Merge branch 'master' into tablelist check-in: 93bf0308fc user: peter.spjuth@gmail.com tags: table-list | |
21:16 | Added GUI for selecting ancestor Closed-Leaf check-in: 973d18ceb6 user: peter.spjuth@gmail.com tags: trunk | |
2010-11-07
| ||
20:20 | Merge branch 'master' into tablelist check-in: a2c892dc70 user: peter.spjuth@gmail.com tags: table-list | |
Changes
Changes to Changes.
1 2 3 4 5 6 7 | 2010-11-07 Added tkdnd support. [FR 5125] 2010-11-07 Autodetect line endings in conflict file. Allow line ending selection in merge save. [FR 5160] Added menu bar to merge window. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | 2011-04-30 Improved three-way merge. Highlight conflicts and navigate directly between conflicts. Include status for each merge chunk to see the descision made. Added Goto menu in merge window to get fewer toolbar buttons. Autodetect line endings in ancestor file to select merge output. 2011-04-28 Code cleanup to get clean Nagelfar run 2011-04-28 Added three-way merge. Cmd line options -a and -fine. 2011-04-24 Added basic GUI for plugin selection. 2011-04-22 Merging did not work properly if alignement was used. [Bug 9925] 2011-04-11 Support files and revisions with -review in Fossil. Support revisions with -review in Git. New DiffUtil has a fallback to pure Tcl LCS. 2011-04-05 Added -pluginlist option. Added Paste Patch command in Tools. 2011-04-04 Support list of files with -review. Support commit from -review. Support commit in Git and Fossil. Release 2.5 2011-03-31 Added support for Fossil revision control. 2010-11-07 Added tkdnd support. [FR 5125] 2010-11-07 Autodetect line endings in conflict file. Allow line ending selection in merge save. [FR 5160] Added menu bar to merge window. |
︙ | ︙ |
Changes to Eskil.html.
︙ | ︙ | |||
24 25 26 27 28 29 30 | but still found Tcl annoying at the time.)<br> I have used it a lot during the years and lately it has received enough polish to grant a public release. <p> Pronunciation: The E is short, like in "set", the rest is like "skill". <p> Any feedback, good or bad, can be sent to | | | | > | | | > > > > > > > > > > > > > > | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | but still found Tcl annoying at the time.)<br> I have used it a lot during the years and lately it has received enough polish to grant a public release. <p> Pronunciation: The E is short, like in "set", the rest is like "skill". <p> Any feedback, good or bad, can be sent to <peter <i>dot</i> spjuth <i>at</i> gmail <i>dot</i> com> <p> It is similar but unrelated to <a href="http://wiki.tcl.tk/tkdiff">TkDiff</a>. <a name="EskilFeatures"></a><h3>Features</h3> <ul> <li>Highlights changes within a line.</li> <li>Matches similar lines within a changed block to better show changed lines that are adjacent to added/removed lines.</li> <li>Directory diff.</li> <li>CVS/RCS/ClearCase/GIT/SVN/BZR/HG/Perforce/Fossil diff. Conflict merge.</li> <li>Commit changes directly from Eskil.</li> <li>View patch, from file or clipboard.</li> <li>Print to PDF.</li> <li>"Clip diff"</li> <li>Plugins for preprocessing files.</li> <li>Alignment and block diff functions for tricky diffs.</li> <li>Edit and Save file from diff window.</li> <li><a href="http://wiki.tcl.tk/starkit">Starkit</a> browsing.</li> </ul> <a name="EskilDownload"></a><h3>Download</h3> Version 2.5:<br> Is available from the <a href="https://developer.berlios.de/projects/eskil/">Project page</a> both as a Starkit and as Starpacks for Windows, Linux and Solaris. <p> The license for the application source is GPL but the bundled packages are under the same license as Tcl. <p>More information about <a href="http://wiki.tcl.tk/starkit">Starkits</a> and <a href="http://wiki.tcl.tk/starpack">Starpacks</a>. <a name="EskilScreenshots"></a><h3>Screenshots</h3> <img src="eskil/eskil1.png"> <p> A "zoom" feature for long lines.<p> <img src="eskil/eskil2.png"><br> <a name="EskilChanges"></a><h3>Changes</h3> Changes in v2.5 (2011-04-01):<br> <ul> <li> Requires Tcl 8.5.</li> <li> Plugins: Added dump, better documentation.</li> <li> Dir diff: Added step down.</li> <li> Dir diff: Redesigned to display less.</li> <li> Support for Perforce and Fossil.</li> <li> Allow zero lines of context.</li> <li> Detect and display annotation in patch view.</li> <li> Select colors for PDF print. Command line options for PDF.</li> <li> Removed support for Postscript output.</li> <li> Support File Drop with TkDnd.</li> <li> Handle line endings in conflict and merge.</li> </ul> Changes in v2.4 (2009-01-08):<br> <ul> <li> Completely redesigned directory diff.</li> <li> Added a log viewer in revision mode.</li> <li> Added color option for unchanged text.</li> <li> Plugins support.</li> <li> Support for Subversion, Mercurial and Bazaar.</li> |
︙ | ︙ |
Changes to Makefile.
1 2 3 | #---------------------------------------------------------------------- # Make file for Eskil #---------------------------------------------------------------------- | < < | | > > | | < | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #---------------------------------------------------------------------- # Make file for Eskil #---------------------------------------------------------------------- VERSION = 26 # Path to the TclKits used for creating StarPacks. TCLKIT = /home/peter/tclkit/v85 TCLKIT_LINUX = $(TCLKIT)/tclkit-8.5.8 TCLKIT_SOLARIS = $(TCLKIT)/tclkit-solaris-sparc TCLKIT_WIN = $(TCLKIT)/tclkit-win32.upx.exe # Path to the libraries used STYLE = /home/peter/src/packages/style GRIFFIN = /home/peter/tclkit/griffin.vfs/lib/griffin TEXTSEARCH = /home/peter/src/textsearch DIFFUTIL = /home/peter/src/DiffUtilTcl/lib.vfs/DiffUtil WCB = /home/peter/src/packages/wcb3.0 PDF4TCL = /home/peter/src/pdf4tcl/pkg SNIT = /home/peter/tcl/tcllib/modules/snit STRUCT = /home/peter/tcl/tcllib/modules/struct CMDLINE = /home/peter/tcl/tcllib/modules/cmdline TWAPI = /home/peter/src/packages/twapi TKDND = /home/peter/src/packages/tkdnd/lib/tkdnd1.0 # Tools NAGELFAR = nagelfar all: setup SRCFILES = src/eskil.tcl src/clip.tcl src/dirdiff.tcl src/help.tcl src/map.tcl \ src/print.tcl src/registry.tcl src/rev.tcl \ src/compare.tcl src/merge.tcl src/printobj.tcl src/plugin.tcl #---------------------------------------------------------------- # Setup symbolic links from the VFS to the real files #---------------------------------------------------------------- eskil.vfs/src/eskil.tcl: |
︙ | ︙ | |||
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | cd eskil.vfs/lib ; mkdir snit cd eskil.vfs/lib/snit ; ln -s $(SNIT)/pkgIndex.tcl cd eskil.vfs/lib/snit ; ln -s $(SNIT)/snit.tcl cd eskil.vfs/lib/snit ; ln -s $(SNIT)/snit2.tcl cd eskil.vfs/lib/snit ; ln -s $(SNIT)/main2.tcl cd eskil.vfs/lib/snit ; ln -s $(SNIT)/main1.tcl cd eskil.vfs/lib/snit ; ln -s $(SNIT)/validate.tcl links: eskil.vfs/src/eskil.tcl \ eskil.vfs/examples\ eskil.vfs/doc\ eskil.vfs/plugins\ eskil.vfs/COPYING\ eskil.vfs/lib/griffin\ eskil.vfs/lib/style\ eskil.vfs/lib/textsearch\ eskil.vfs/lib/diffutil\ eskil.vfs/lib/pdf4tcl\ eskil.vfs/lib/snit\ eskil.vfs/lib/tkdnd\ eskil.vfs/lib/wcb setup: links #---------------------------------------------------------------- # Testing #---------------------------------------------------------------- spell: @cat doc/*.txt | ispell -d british -l | sort -u # Create a common "header" file for all source files. eskil_h.syntax: $(SRCFILES) src/eskil.syntax @echo Creating syntax header file... | > > > > > > > > > > | | | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | cd eskil.vfs/lib ; mkdir snit cd eskil.vfs/lib/snit ; ln -s $(SNIT)/pkgIndex.tcl cd eskil.vfs/lib/snit ; ln -s $(SNIT)/snit.tcl cd eskil.vfs/lib/snit ; ln -s $(SNIT)/snit2.tcl cd eskil.vfs/lib/snit ; ln -s $(SNIT)/main2.tcl cd eskil.vfs/lib/snit ; ln -s $(SNIT)/main1.tcl cd eskil.vfs/lib/snit ; ln -s $(SNIT)/validate.tcl eskil.vfs/lib/struct: cd eskil.vfs/lib ; mkdir struct cd eskil.vfs/lib/struct ; ln -s $(STRUCT)/pkgIndex.tcl cd eskil.vfs/lib/struct ; ln -s $(STRUCT)/list.tcl eskil.vfs/lib/cmdline: cd eskil.vfs/lib ; ln -s $(CMDLINE) cmdline links: eskil.vfs/src/eskil.tcl \ eskil.vfs/examples\ eskil.vfs/doc\ eskil.vfs/plugins\ eskil.vfs/COPYING\ eskil.vfs/lib/griffin\ eskil.vfs/lib/style\ eskil.vfs/lib/textsearch\ eskil.vfs/lib/diffutil\ eskil.vfs/lib/pdf4tcl\ eskil.vfs/lib/snit\ eskil.vfs/lib/struct\ eskil.vfs/lib/cmdline\ eskil.vfs/lib/tkdnd\ eskil.vfs/lib/wcb setup: links #---------------------------------------------------------------- # Testing #---------------------------------------------------------------- spell: @cat doc/*.txt | ispell -d british -l | sort -u NAGELFARFLAGS = -s syntaxdb86.tcl -filter "*Non constant definition*" -quiet # Create a common "header" file for all source files. eskil_h.syntax: $(SRCFILES) src/eskil.syntax @echo Creating syntax header file... @$(NAGELFAR) $(NAGELFARFLAGS) -header eskil_h.syntax $(SRCFILES) check: eskil_h.syntax @echo Checking... @for i in $(SRCFILES); do $(NAGELFAR) $(NAGELFARFLAGS) eskil_h.syntax $$i ; done test: @./tests/all.tcl #---------------------------------------------------------------- # Coverage #---------------------------------------------------------------- |
︙ | ︙ |
Changes to doc/cmdline.txt.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | -nodiff : Normally, if there are enough information on the command line to run diff, Eskil will do so unless this option is specified. -dir : Start in directory diff mode. Ignores other args. -clip : Start in clip diff mode. Ignores other args. -patch : View patch file. -context <n>: Show only differences, with <n> lines of context. -foreach : Open one diff window per file listed. -close : Close windows with no changes. -noparse : Eskil can perform analysis of changed blocks to -line : improve display. See online help for details. -smallblock : The default. Do block analysis on small blocks. -block : Full block analysis. This can be slow if there are large change blocks. -char : The analysis of changes can be done on either -word : character or word basis. -char is the default. -noignore : Don't ignore any whitespace. -b : Ignore space changes. Default. -w : Ignore all spaces. -nocase : Ignore case changes. -nodigit : Ignore digit changes. -nokeyword : In directory diff, ignore $ Keywords: $ -prefix <str> : Care mainly about words starting with "str". -preprocess <pair> : TBW -r <ver> : Version info for version control mode. -conflict : Treat file as a merge conflict file and enter merge mode. -o <file> : Specify merge result output file. -browse : Automatically bring up file dialog after starting. -server : Set up Eskil to be controllable from the outside. -print <file> : Generate PDF and exit. -printCharsPerLine <n> : Adapt font size for this line length and wrap. (80) -printPaper <paper> : Select paper size (a4) -printHeaderSize <n> : Font size for page header (10) -printColorChange <RGB> : Color for change (1.0 0.7 0.7) -printColorOld <RGB> : Color for old text (0.7 1.0 0.7) -printColorNew <RGB : Color for new text (0.8 0.8 1.0) | > > > > > > > > | > > > | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | -nodiff : Normally, if there are enough information on the command line to run diff, Eskil will do so unless this option is specified. -dir : Start in directory diff mode. Ignores other args. -clip : Start in clip diff mode. Ignores other args. -patch : View patch file. - : Read patch file from standard input, to allow pipes. -review : View revision control tree as a patch. -context <n>: Show only differences, with <n> lines of context. -foreach : Open one diff window per file listed. -close : Close windows with no changes. -noparse : Eskil can perform analysis of changed blocks to -line : improve display. See online help for details. -smallblock : The default. Do block analysis on small blocks. -block : Full block analysis. This can be slow if there are large change blocks. -char : The analysis of changes can be done on either -word : character or word basis. -char is the default. -noignore : Don't ignore any whitespace. -b : Ignore space changes. Default. -w : Ignore all spaces. -nocase : Ignore case changes. -nodigit : Ignore digit changes. -nokeyword : In directory diff, ignore $ Keywords: $ -nonewline : Try to ignore newline changes. -nonewline+ : Try to ignore newline changes, and don't display. -prefix <str> : Care mainly about words starting with "str". -preprocess <pair> : TBW -r <ver> : Version info for version control mode. -cvs : Detect CVS first, if multiple version systems are used. -svn : Detect SVN first, if multiple version systems are used. -a <file> : Give anscestor file for three way merge. -conflict : Treat file as a merge conflict file and enter merge mode. -o <file> : Specify merge result output file. -fine : Use fine grained chunks. Useful for merging. -browse : Automatically bring up file dialog after starting. -server : Set up Eskil to be controllable from the outside. -print <file> : Generate PDF and exit. -printCharsPerLine <n> : Adapt font size for this line length and wrap. (80) -printPaper <paper> : Select paper size (a4) -printHeaderSize <n> : Font size for page header (10) -printColorChange <RGB> : Color for change (1.0 0.7 0.7) -printColorOld <RGB> : Color for old text (0.7 1.0 0.7) -printColorNew <RGB : Color for new text (0.8 0.8 1.0) -plugin <name> : Preprocess files using plugin. -plugininfo <info> : Pass info to plugin (plugin specific) -pluginlist : List known plugins -plugindump <plugin> : Dump plugin source to stdout -limit <lines> : Do not process more than <lines> lines. To list all options matching a prefix, run 'eskil --query prefix'. In tcsh use this line to get option completion: complete eskil 'C/-/`eskil --query -`/' |
Changes to doc/eskil.txt.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <b><ul>Commands</ul></b> <b>File Menu</b> Redo Diff \t: Run diff again on the same files. Open Both \t: Select two files, run diff. Open Left File \t: Select a file for left window, run diff Open Right File \t: Select a file for right window, run diff Open Conflict File\t: Select a file containing conflicts such as from \t a CVS merge. Open Patch File \t: Display a patch file created by diff -c or diff -u. Revision Diff \t: Select one revision controlled file. Print PDF \t: Print diff to PDF file. Close \t: Close this window. Quit \t: Guess <b>Options Menu</b> Font \t: Select font and fontsize for the two main text windows Ignore \t: Diff options for ignoring e.g. whitespace Parse \t: Additional parsing made by Eskil to improve the display. \t See examples below. \t Nothing: No parsing made. \t Lines : When there is a changed block with the same number \t of lines in both right and left files, Eskil \t compares corresponding lines and tries to highlight \t only the part that has been changed. \t Blocks : When the number of lines in a changed block is not \t the same in both files, Eskil tries to find lines \t that look the same and place them abreast. The "small" \t version do not parse big blocks to avoid long runs. \t The Char and Word options selects if the line parsing should \t highlight full words only, or check single characters. \t Mark last : Last change of a line is underlined Colours\t: Choose highlight colours. Context\t: You can select that only differing lines shall be displayed, \t and how many surrounding lines are shown. Save default\t: Save current option settings in ~/.eskilrc <b>Search Menu</b> Find \t: Search dialog Find next \t: Repeat search Find prev \t: Repeat search backwards <b>Tools Menu</b> New Diff Window \t : Open another diff window. Directory Diff \t : Window for comparing directories Clip Diff \t : Gives two areas where you can paste text and diff them. Merge \t : Perform a two way merge. Edit Mode \t : (new edit mode, to be described) Clear Align \t : Clear alignment info for this diff. The effect does not \t show until you do "Redo Diff". | > > > > < > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | <b><ul>Commands</ul></b> <b>File Menu</b> Redo Diff \t: Run diff again on the same files. Open Both \t: Select two files, run diff. Open Left File \t: Select a file for left window, run diff Open Right File \t: Select a file for right window, run diff Open Ancestor File\t: Select ancestor for threeway diff, rerun and merge Open Conflict File\t: Select a file containing conflicts such as from \t a CVS merge. Open Patch File \t: Display a patch file created by diff -c or diff -u. Revision Diff \t: Select one revision controlled file. Print PDF \t: Print diff to PDF file. Close \t: Close this window. Quit \t: Guess <b>Options Menu</b> Font \t: Select font and fontsize for the two main text windows Ignore \t: Diff options for ignoring e.g. whitespace Preprocess\t: Options for making string substitution before comparing. Parse \t: Additional parsing made by Eskil to improve the display. \t See examples below. \t Nothing: No parsing made. \t Lines : When there is a changed block with the same number \t of lines in both right and left files, Eskil \t compares corresponding lines and tries to highlight \t only the part that has been changed. \t Blocks : When the number of lines in a changed block is not \t the same in both files, Eskil tries to find lines \t that look the same and place them abreast. The "small" \t version do not parse big blocks to avoid long runs. \t The Char and Word options selects if the line parsing should \t highlight full words only, or check single characters. \t Mark last : Last change of a line is underlined Colours\t: Choose highlight colours. Context\t: You can select that only differing lines shall be displayed, \t and how many surrounding lines are shown. Toolbar\t: Show/hide toolbar Save default\t: Save current option settings in ~/.eskilrc <b>Search Menu</b> Find \t: Search dialog Find next \t: Repeat search Find prev \t: Repeat search backwards <b>Tools Menu</b> New Diff Window \t : Open another diff window. Directory Diff \t : Window for comparing directories Clip Diff \t : Gives two areas where you can paste text and diff them. Merge \t : Perform a two way merge. Edit Mode \t : (new edit mode, to be described) Paste Patch \t : Display a patch from clipboard. Clear Align \t : Clear alignment info for this diff. The effect does not \t show until you do "Redo Diff". Rev 1/2 Fields \t: In Revision mode, these field are selects versions to be \t compared. Log Button \t: Show revision control log between shown files. Commit Button \t: Commit shown differences to version control. Prev Diff Button\t: Scrolls to the previous differing block, or to the top \t if there are no more diffs. Next Diff Button\t: Scrolls to the next differing block, or to the bottom \t if there are no more diffs. Equal sign\t: Above the vertical scrollbar, a "=" will appear if the files \t are equal. While the external diff executes a "*" is shown |
︙ | ︙ | |||
83 84 85 86 87 88 89 | You can, for each difference, select which version you want to appear in the output file. The buttons "LR", "L", "R" and "RL" select the lines from the left file, right file or both files. "Prev" and "Next" buttons moves between differences. "All L" and "All R" buttons select "L" or "R" for all differences. "Pure" ... "Save" saves the merge result to a file. | | | | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | You can, for each difference, select which version you want to appear in the output file. The buttons "LR", "L", "R" and "RL" select the lines from the left file, right file or both files. "Prev" and "Next" buttons moves between differences. "All L" and "All R" buttons select "L" or "R" for all differences. "Pure" ... "Save" saves the merge result to a file. On the keyboard, Up and Down keys means the same as "Prev" and "Next". Left and Right keys selects "L" and "R". Shift-Up and Shift-Down jumps 10 changes, or if there are conflicts jumps to next conflict. When saved it is the contents of the text widget that is saved which means you can hand edit there if you are careful. Press Escape to bring focus out of the text and make cursor keys navigate between changes. <b><ul>Examples of effects of parse options.</ul></b> Below are two example files, and five different results when using different options with those files. <example>Left file: \tRight file: <pre>NET '/I$1/N$1454' IC2-15 IC5-7 \tNET '/I$1/N$1454' IC1-4 IC2-15 IC5-2 IC5-7 |
︙ | ︙ |
Changes to doc/plugins.txt.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Eskil provides a plugin system where a plugin can preprocess data before being compared and displayed. The command line options for plugins are: -plugin plugin : Use plugin -plugininfo info : Pass info to plugin (plugin specific) -plugindump plugin : Dump plugin source to stdout A plugin is a Tcl script that must follow a specific format. Dump one of the included plugins to see what it looks like. The plugin is executed in a safe interpreter and thus cannot do any damage. A plugin is set up with these global variables filled in: ::WhoAmI : The name of the plugin ::Info : The contents of -plugininfo parameter ::Pref : A copy if Eskil's internal preferences array. Example plugins are included in the kit. | > < < | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | Eskil provides a plugin system where a plugin can preprocess data before being compared and displayed. The command line options for plugins are: -plugin plugin : Use plugin -plugininfo info : Pass info to plugin (plugin specific) -plugindump plugin : Dump plugin source to stdout -pluginlist : List known plugins A plugin is a Tcl script that must follow a specific format. Dump one of the included plugins to see what it looks like. The plugin is executed in a safe interpreter and thus cannot do any damage. A plugin is set up with these global variables filled in: ::WhoAmI : The name of the plugin ::Info : The contents of -plugininfo parameter ::Pref : A copy if Eskil's internal preferences array. Example plugins are included in the kit. A plugin may give a result that has a line-by-line correspondence to the original, in which case the preprocessed data is used for comparing while the original is used for displaying. The main plugin procedure returns 0 to signify this case. If the plugin procedure returns 1, the processed data is used also for displaying. When searching for a plugin "x", files "x" and "x.tcl" will match. The search path is current directory, "plugins" directory, the directory where Eskil is installed, "plugins" directory where Eskil is installed, and also the internal "plugins" wrapped into Eskil. |
Changes to doc/revision.txt.
1 | Eskil can compare versions in revision control systems. | | | 1 2 3 4 5 6 7 8 9 | Eskil can compare versions in revision control systems. Currently RCS, CVS, Git, Fossil, Mercurial, Bazaar, Subversion, Perforce and ClearCase are supported. If you specify only one file on the command line to Eskil, it will automatically detect if the file is under revision control and enter revision control mode. By default the local file is compared against the latest checked in version. This is for the common case when you just want to know what you have changed before checking in. You can use the -r option to select which versions to compare. It works like it does in "cvs diff". Examples: |
︙ | ︙ | |||
31 32 33 34 35 36 37 | <pre>hg diff | eskil -</pre> <pre>git diff -p --diff-filter=M master | eskil -</pre> <ul>View all changes</ul> If the command line option -review is used. Eskil will generate a patch for the current tree and display it as in patch mode. | | > > > > > > > | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | <pre>hg diff | eskil -</pre> <pre>git diff -p --diff-filter=M master | eskil -</pre> <ul>View all changes</ul> If the command line option -review is used. Eskil will generate a patch for the current tree and display it as in patch mode. E.g. in a Mercurial directory, these show the same thing: <pre>eskil -preview</pre> <pre>hg diff | eskil -</pre> If file names are given after -review, only the listed files are included. If supported, the Commit button will be enabled allowing the viewed differences to be committed. <ul>RCS/CVS</ul> For RCS and CVS the arguments to -r are standard version numbers just like to their -r options. RCS style -r\u003crev\u003e is allowed. If a revision is an integer, it is added to the last number in the current version, thus giving relative versions. E.g. -1 gives the second to last version. <ul>Subversion</ul> For Subversion the arguments to -r are standard version numbers just like its -r option. If a revision is a negative integer, the log is searched backwards for earlier versions. E.g. -1 gives the second to last version. <ul>Git</ul> For Git -r <rev> is passed to show, as in "git show <rev>:<file>". <ul>Fossil</ul> For Fossil -r <rev> is passed to finfo, as in "fossil finfo -p <file> -r <rev>". <ul>Mercurial</ul> For Mercurial -r works as in "hg cat -r". <ul>Bazaar</ul> For Bazaar -r works as in "bzr cat -r". |
︙ | ︙ |
Changes to doc/tutorial.txt.
︙ | ︙ | |||
35 36 37 38 39 40 41 42 43 44 45 46 47 48 | Now those lines are remembered, and you could add more alignment pairs before you proceed with regenerating the view. <bullet>\u2022\tSelect menu File->Redo Diff.</bullet> Scroll down and see that the lines are next to each other. Also note that their line numbers are underlined. You can clear the alignment information in the right-click menu over a line or by selecting the menu Tools->Clear Align. <b>Regular expression preprocessing</b> Double click on enum.c to bring up the diff. [write something here to explain the problem and the goal] [add reference to re_syntax and regsub manuals] <bullet> \u2022\tSelect menu Options->Preprocess. | > > > > > > > > | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | Now those lines are remembered, and you could add more alignment pairs before you proceed with regenerating the view. <bullet>\u2022\tSelect menu File->Redo Diff.</bullet> Scroll down and see that the lines are next to each other. Also note that their line numbers are underlined. You can clear the alignment information in the right-click menu over a line or by selecting the menu Tools->Clear Align. <b>Three way merge</b> <bullet> \u2022\tDouble click on merge.txt to bring up the diff. \u2022\tSelect menu File->Open Ancestor File. \u2022\tSelect file mergeanc.txt </bullet> The merge window will appear with most changes merged. Conflicts are marked with gray, and a row of asterisks in the status bar. Conflicts are resolved to the right initially. Navigate between conflicts using shift-up/down keys. Select side with left/right keys. <b>Regular expression preprocessing</b> Double click on enum.c to bring up the diff. [write something here to explain the problem and the goal] [add reference to re_syntax and regsub manuals] <bullet> \u2022\tSelect menu Options->Preprocess. |
︙ | ︙ |
Added examples/dir1/merge.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 0 1 Added left x 2 3 4 Added right 5 6 7 Changed same 8a 9 10 Changed different 12a 13 14 Deleted left 17 18 Deleted right 19 20 21 Left: Add+change Right: change xx 22a 23 24 Left: change Right add+change 25a 26 27 Left: Delete Right: change 29 30 Left: change Right: delete 31a 32 33 Added same xxx 34 35 36 Deleted same 38 39 Changed adjacent 40a 41 42 Left: Add+change Right: change same xxxx 43a 44 45 Left: change same Right: add+change 46a 47 48 Left: change Right: deleted block 49 50a 51 52 Added different xxxxx 53 54 55 Left mixed change 57x 59 60 Right mixed change 61 62 63 64 65 Both added multiple xx1 xx2 66 67 |
Added examples/dir1/mergeanc.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | 0 1 Added left 2 3 4 Added right 5 6 7 Changed same 8 9 10 Changed different 12 13 14 Deleted left 16 17 18 Deleted right 19 20 21 Left: Add+change Right: change 22 23 24 Left: change Right add+change 25 26 27 Left: Delete Right: change 28 29 30 Left: change Right: delete 31 32 33 Added same 34 35 36 Deleted same 37 38 39 Changed adjacent 40 41 42 Left: Add+change Right: change same 43 44 45 Left: change same Right: add+change 46 47 48 Left: change Right: deleted block 49 50 51 52 Added different 53 54 55 Left mixed change 56 57 58 59 60 Right mixed change 61 62 63 64 65 Both added multiple 66 67 |
Added examples/dir2/merge.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | 0 1 Added left 2 3 4 Added right y 5 6 7 Changed same 8a 9 10 Changed different 12b 13 14 Deleted left 16 17 18 Deleted right 20 21 Left: Add+change Right: change 22b 23 24 Left: change Right add+change yy 25b 26 27 Left: Delete Right: change 28a 29 30 Left: change Right: delete 32 33 Added same xxx 34 35 36 Deleted same 38 39 Changed adjacent 40 41a 42 Left: Add+change Right: change same 43a 44 45 Left: change same Right: add+change yyyy 46a 47 48 Left: change Right: deleted block 52 Added different yyyyy 53 54 55 Left mixed change 56 57 58 59 60 Right mixed change 61x 63x 64 65 Both added multiple yy1 yy2 66 67 |
Changes to src/clip.tcl.
︙ | ︙ | |||
129 130 131 132 133 134 135 | } proc makeClipDiffWin {} { set top .clipdiff if {[winfo exists $top] && [winfo toplevel $top] eq $top} { raise $top focus -force $top | | | | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | } proc makeClipDiffWin {} { set top .clipdiff if {[winfo exists $top] && [winfo toplevel $top] eq $top} { raise $top focus -force $top return $top } destroy $top toplevel $top eskilRegisterToplevel $top wm title $top "Clip Diff" wm protocol $top WM_DELETE_WINDOW "cleanupAndExit $top" set t1 [Scroll both \ text $top.t1 -width 60 -height 35 -font myfont] set t2 [Scroll both \ text $top.t2 -width 60 -height 35 -font myfont] |
︙ | ︙ | |||
192 193 194 195 196 197 198 199 | } grid $top.f - -sticky we grid $top.t1 $top.t2 -sticky news grid $top.t2 -padx {2 0} grid rowconfigure $top 1 -weight 1 grid columnconfigure $top {0 1} -weight 1 } | > | 192 193 194 195 196 197 198 199 200 | } grid $top.f - -sticky we grid $top.t1 $top.t2 -sticky news grid $top.t2 -padx {2 0} grid rowconfigure $top 1 -weight 1 grid columnconfigure $top {0 1} -weight 1 return $top } |
Changes to src/dirdiff.tcl.
︙ | ︙ | |||
434 435 436 437 438 439 440 | set dst $lf } elseif {$lp ne ""} { set dst [file join $lp [file tail $src]] } else { return } } else { | | | 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 | set dst $lf } elseif {$lp ne ""} { set dst [file join $lp [file tail $src]] } else { return } } else { error "Bad from argument to CopyFile: $from" } if {[file exists $dst]} { if {[tk_messageBox -icon question -title "Overwrite file?" -message \ "Copy\n$src\noverwriting\n$dst ?" -type yesno] eq "yes"} { file copy -force $src $dst # FIXA: update file info in tree too |
︙ | ︙ | |||
844 845 846 847 848 849 850 | snit::widget DirDiff { hulltype toplevel widgetclass Toplevel component tree variable statusVar constructor {args} { | | | 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 | snit::widget DirDiff { hulltype toplevel widgetclass Toplevel component tree variable statusVar constructor {args} { eskilRegisterToplevel $win wm title $win "Eskil Dir" wm protocol $win WM_DELETE_WINDOW [list cleanupAndExit $win] install tree using DirCompareTree $win.dc \ -leftdirvariable ::dirdiff(leftDir) \ -rightdirvariable ::dirdiff(rightDir) \ -statusvar [myvar statusVar] |
︙ | ︙ | |||
906 907 908 909 910 911 912 | $win.m add cascade -label "Help" -underline 0 -menu $win.m.help menu $win.m.help $win.m.help add command -label "Tutorial" -command makeTutorialWin \ -underline 0 $win.m.help add command -label "About" -command makeAboutWin -underline 0 | | | 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 | $win.m add cascade -label "Help" -underline 0 -menu $win.m.help menu $win.m.help $win.m.help add command -label "Tutorial" -command makeTutorialWin \ -underline 0 $win.m.help add command -label "About" -command makeAboutWin -underline 0 if {$::eskil(debug)} { $win.m add cascade -label "Debug" -menu $win.m.md -underline 0 menu $win.m.md if {$::tcl_platform(platform) eq "windows"} { $win.m.md add checkbutton -label "Console" -variable consolestate \ -onvalue show -offvalue hide -command {console $consolestate} $win.m.md add separator } |
︙ | ︙ | |||
1082 1083 1084 1085 1086 1087 1088 | -command "ApplyDirDiffPref ; destroy $top" ttk::button $fb.ap -width 10 -text "Apply" -command ApplyDirDiffPref ttk::button $fb.ca -width 10 -text "Cancel" -command "destroy $top" grid $fb.ok $fb.ap $fb.ca -padx 3 -pady 3 grid columnconfigure $fb {0 1 2} -uniform a -weight 1 pack $fb -side bottom -fill x | | | 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 | -command "ApplyDirDiffPref ; destroy $top" ttk::button $fb.ap -width 10 -text "Apply" -command ApplyDirDiffPref ttk::button $fb.ca -width 10 -text "Cancel" -command "destroy $top" grid $fb.ok $fb.ap $fb.ca -padx 3 -pady 3 grid columnconfigure $fb {0 1 2} -uniform a -weight 1 pack $fb -side bottom -fill x pack $check $opts $filter -side "top" -fill x } # Experimental... #preprocess filter pa namnen sa man kan jamfora bibliotek #med andrade namn. proc makeRegSubWin {} { set top .ddregsub |
︙ | ︙ | |||
1123 1124 1125 1126 1127 1128 1129 1130 | set ::dirdiff(leftDir) "" } if {![info exists ::dirdiff(rightDir)]} { set ::dirdiff(rightDir) "" } destroy .dirdiff DirDiff .dirdiff } | > | 1123 1124 1125 1126 1127 1128 1129 1130 1131 | set ::dirdiff(leftDir) "" } if {![info exists ::dirdiff(rightDir)]} { set ::dirdiff(rightDir) "" } destroy .dirdiff DirDiff .dirdiff return .dirdiff } |
Changes to src/eskil.syntax.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | ##nagelfar syntax textSearch::searchMenu x ##nagelfar syntax textSearch::enableSearch x x* ##nagelfar syntax DiffUtil::LocateDiffExe x ###nagelfar syntax DiffUtil::diffStrings o* x x ##nagelfar syntax dde s x ##nagelfar syntax safeLoad x n ##nagelfar syntax helpWin x x ##nagelfar syntax commonYScroll x x* ##nagelfar syntax locateEditor n ##nagelfar syntax locateTmp n ##nagelfar syntax wcb::cancel 0 ##nagelfar syntax wcb::callback 4 ##nagelfar syntax vfs::mk4::Mount r 2 ##nagelfar syntax vfs::unmount 1 | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | ##nagelfar syntax textSearch::searchMenu x ##nagelfar syntax textSearch::enableSearch x x* ##nagelfar syntax DiffUtil::LocateDiffExe x ###nagelfar syntax DiffUtil::diffStrings o* x x ##nagelfar syntax dde s x ##nagelfar syntax dnd s x* ##nagelfar syntax safeLoad x n ##nagelfar syntax helpWin x x ##nagelfar syntax commonYScroll x x* ##nagelfar syntax locateEditor n ##nagelfar syntax locateTmp n ##nagelfar syntax wcb::cancel 0 ##nagelfar syntax wcb::callback 4 ##nagelfar syntax vfs::mk4::Mount r 2 ##nagelfar syntax vfs::unmount 1 ###nagelfar syntax ttk::entryX x p* ##nagelfar syntax ::tk::GetSelection x x ##nagelfar syntax ::tk::ScrollButton2Down x x x ##nagelfar syntax console x ##nagelfar syntax registry x x x ##nagelfar syntax pdf4tcl::getPaperSize x ##nagelfar syntax pdf4tcl::getPaperSizeList ##nagelfar syntax twapi::get_foreground_window ##nagelfar syntax twapi::get_window_coordinates x ##nagelfar syntax twapi::get_window_at_location x x ##nagelfar syntax twapi::set_focus x ##nagelfar syntax twapi::send_keys x ##nagelfar syntax twapi::get_window_coordinates x # Operators ##nagelfar syntax + x* ##nagelfar syntax - x x* ##nagelfar syntax * x* ##nagelfar syntax / x x* # This is the generic definitions needed for Snit. ##nagelfar syntax _stdclass_snit s x* ##nagelfar subcmd _stdclass_snit destroy configurelist configure ##nagelfar syntax _stdclass_snit\ destroy 0 ##nagelfar syntax _stdclass_snit\ configurelist x ##nagelfar syntax _stdclass_snit\ configure x* ##nagelfar syntax snit::type do=_stdclass_snit cn ##nagelfar syntax snit::type::method dm ##nagelfar syntax snit::type::constructor cv ##nagelfar syntax snit::type::destructor cl ##nagelfar syntax snit::type::option x p* ##nagelfar syntax snit::type::component x ##nagelfar syntax snit::type::delegate x* ##nagelfar syntax snit::type::install s x* ##nagelfar syntax snit::widgetadaptor do=_stdclass_snit cn ##nagelfar syntax snit::widgetadaptor::method dm ##nagelfar syntax snit::widgetadaptor::constructor cv ##nagelfar syntax snit::widgetadaptor::destructor cl ##nagelfar syntax snit::widgetadaptor::delegate x* ##nagelfar syntax snit::widgetadaptor::installhull x* ##nagelfar syntax snit::widgetadaptor::from l x* ##nagelfar syntax snit::widgetadaptor::component x ##nagelfar syntax snit::widgetadaptor::install s x* ##nagelfar syntax snit::widgetadaptor::option x p* ##nagelfar syntax snit::widget do=_stdclass_snit cn ##nagelfar syntax snit::widget::method dm ##nagelfar syntax snit::widget::constructor cv ##nagelfar syntax snit::widget::destructor cl ##nagelfar syntax snit::widget::delegate x* ##nagelfar syntax snit::widget::installhull x* ##nagelfar syntax snit::widget::from l x* ##nagelfar syntax snit::widget::hulltype x ##nagelfar syntax snit::widget::widgetclass x ##nagelfar syntax snit::widget::myvar l ##nagelfar syntax snit::widget::mymethod x x* ##nagelfar return snit::widget::myvar varName ##nagelfar syntax snit::widget::component x ##nagelfar syntax snit::widget::install s x* ##nagelfar syntax snit::widget::option x p* # This is the annotation needed for this object definition ##nagelfar syntax eskilprint dc=_obj,eskilprint p* ##nagelfar option eskilprint -file -cpl -cpln -headsize -headleft -headright -headnpages -margin -paper ##nagelfar return eskilprint _obj,eskilprint ##nagelfar subcmd+ _obj,eskilprint text newLine ##nagelfar implicitvar snit::type::eskilprint self\ _obj,eskilprint width height pdf hoy fontsize linesize nlines ox1 ox2 oy page options # This is the annotation needed for this object definition ##nagelfar syntax DirDiff dc=_obj,DirDiff p* ###nagelfar option DirDiff ##nagelfar return DirDiff _obj,DirDiff ##nagelfar subcmd+ _obj,DirDiff text newLine ##nagelfar implicitvar snit::widget::DirDiff self\ _obj,DirDiff statusVar hull win self tree # This is the annotation needed for this object definition ##nagelfar syntax DirCompareTree dc=_obj,DirCompareTree p* ##nagelfar option DirCompareTree -leftdirvariable -rightdirvariable -statusvar ##nagelfar return DirCompareTree _obj,DirCompareTree ##nagelfar subcmd+ _obj,DirCompareTree text newLine ##nagelfar implicitvar snit::widget::DirCompareTree self\ _obj,DirCompareTree hull win self tree hsb vsb options AfterId PauseBgProcessing IdleQueue IdleQueueArr leftMark rightMark leftDir rightDir # This is the annotation needed for this object definition ##nagelfar syntax ttk::entryX dc=_obj,ttk::entryX p* ##nagelfar option ttk::entryX -width -textvariable -style ##nagelfar return ttk::entryX _obj,ttk::entryX ##nagelfar subcmd+ _obj,ttk::entryX text newLine ##nagelfar implicitvar snit::widgetadaptor::ttk::entryX self\ _obj,ttk::entryX hull win self options |
Changes to src/eskil.tcl.
1 2 3 4 5 | #!/bin/sh #---------------------------------------------------------- -*- tcl -*- # # Eskil, a Graphical frontend to diff # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/bin/sh #---------------------------------------------------------- -*- tcl -*- # # Eskil, a Graphical frontend to diff # # Copyright (c) 1998-2011, Peter Spjuth (peter.spjuth@gmail.com) # # Usage # Do 'eskil' for interactive mode # Do 'eskil --help' for command line usage # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by |
︙ | ︙ | |||
21 22 23 24 25 26 27 | # # You should have received a copy of the GNU General Public License # along with this program; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # #---------------------------------------------------------------------- | < < | | | > | | | | | | | | | | | | | | | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | # # You should have received a copy of the GNU General Public License # along with this program; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # #---------------------------------------------------------------------- # the next line restarts using tclsh \ exec tclsh "$0" "$@" package require Tcl 8.5 # Stop Tk from meddling with the command line by copying it first. set ::eskil(argv) $::argv set ::eskil(argc) $::argc set ::argv {} set ::argc 0 set ::eskil(debug) 0 set ::eskil(diffver) "Version 2.5+ 2011-04-30" set ::eskil(thisScript) [file join [pwd] [info script]] namespace import tcl::mathop::+ namespace import tcl::mathop::- namespace import tcl::mathop::* namespace import tcl::mathop::/ # Do initalisations for needed packages and globals. # This is not run until needed to speed up command line error reporting. proc Init {} { package require Tk 8.4 catch {package require textSearch} package require wcb package require snit if {[catch {package require psballoon}]} { # Add a dummy if it does not exist. proc addBalloon {args} {} } else { namespace import -force psballoon::addBalloon } set ::eskil(thisDir) [file dirname $::eskil(thisScript)] # Follow any link set tmplink $::eskil(thisScript) while {[file type $tmplink] eq "link"} { set tmplink [file readlink $tmplink] set tmplink [file normalize [file join $::eskil(thisDir) $tmplink]] set ::eskil(thisDir) [file dirname $tmplink] } # Get all other source files source $::eskil(thisDir)/clip.tcl source $::eskil(thisDir)/compare.tcl source $::eskil(thisDir)/map.tcl source $::eskil(thisDir)/merge.tcl source $::eskil(thisDir)/registry.tcl source $::eskil(thisDir)/dirdiff.tcl source $::eskil(thisDir)/help.tcl source $::eskil(thisDir)/plugin.tcl source $::eskil(thisDir)/printobj.tcl source $::eskil(thisDir)/print.tcl source $::eskil(thisDir)/rev.tcl set ::util(diffexe) diff # Diff functionality is in the DiffUtil package. package require DiffUtil # Help DiffUtil to find a diff executable, if needed catch {DiffUtil::LocateDiffExe $::eskil(thisScript)} # Figure out a place to store temporary files. locateTmp ::diff(tmpdir) if {$::tcl_platform(platform) eq "windows"} { # Locate CVS if it is in c:/bin if {[auto_execok cvs] eq "" && [file exists "c:/bin/cvs.exe"]} { |
︙ | ︙ | |||
164 165 166 167 168 169 170 | } interp alias {} toplevel {} ttk::toplevel } # Debug function to be able to reread the source even when wrapped in a kit. proc EskilRereadSource {} { | | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | } interp alias {} toplevel {} ttk::toplevel } # Debug function to be able to reread the source even when wrapped in a kit. proc EskilRereadSource {} { set this $::eskil(thisScript) # FIXA: Better detection of starkit? # Maybe look at ::starkit::topdir ? #if {[info exists ::starkit::topdir]} { # puts "Topdir: $::starkit::topdir" #} |
︙ | ︙ | |||
192 193 194 195 196 197 198 199 200 201 202 203 204 205 | puts "Resourcing $this" uplevel \#0 [list source $this] } # This function is called when a toplevel is closed. # If it is the last remaining toplevel, the application quits. # If top = "all" it means quit. proc cleanupAndExit {top} { # A security thing to make sure we can exit. set cont 0 if {[catch { if {$top != "all"} { set i [lsearch $::diff(diffWindows) $top] if {$i >= 0} { | > | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | puts "Resourcing $this" uplevel \#0 [list source $this] } # This function is called when a toplevel is closed. # If it is the last remaining toplevel, the application quits. # If top = "all" it means quit. # If eskil is embedded, this should be used to close an eskil toplevel. proc cleanupAndExit {top} { # A security thing to make sure we can exit. set cont 0 if {[catch { if {$top != "all"} { set i [lsearch $::diff(diffWindows) $top] if {$i >= 0} { |
︙ | ︙ | |||
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | (This is a bug)\nTerminating application." -type ok } if {$cont} return clearTmp exit } # Format a line number proc myFormL {lineNo} { if {![string is integer -strict $lineNo]} {return "$lineNo\n"} return [format "%3d: \n" $lineNo] } # Get a name for a temporary file | > > > > > > > | > > > > | | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | (This is a bug)\nTerminating application." -type ok } if {$cont} return clearTmp exit } # If embedding, tell eskil about any other toplevel, then # cleanupAndExit can be used to get rid of it. proc eskilRegisterToplevel {top} { lappend ::diff(diffWindows) $top } # Format a line number proc myFormL {lineNo} { if {![string is integer -strict $lineNo]} {return "$lineNo\n"} return [format "%3d: \n" $lineNo] } # Get a name for a temporary file # A tail can be given to make the file more recognisable. proc tmpFile {{tail {}}} { if {[info exists ::tmpcnt]} { incr ::tmpcnt } else { set ::tmpcnt 0 } set name "tmpd[pid]a$::tmpcnt" if {$tail ne ""} { append name " [file tail $tail]" } set name [file join $::diff(tmpdir) $name] lappend ::tmpfiles $name return $name } # Delete temporary files proc clearTmp {args} { if {![info exists ::tmpfiles]} { |
︙ | ︙ | |||
356 357 358 359 360 361 362 | incr doingLine2 } # Detect if only newlines has changed within the block, e.g. # when rearranging newlines. # Rearranging newlines in comment blocks usually leads to # words moving across "*", ignore * too. | | > | 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 | incr doingLine2 } # Detect if only newlines has changed within the block, e.g. # when rearranging newlines. # Rearranging newlines in comment blocks usually leads to # words moving across "*", ignore * too. # Returns 0 if the block in not handled here, non-zero if the block is done, # negative if the block is considered not a change. proc ParseBlocksAcrossNewline {top block1 block2} { global doingLine1 doingLine2 set map {{ } {} \t {}} set RE {\n\s*\*?|\s} set equal 0 set visible [expr {$::eskil(ignorenewline) == 1}] |
︙ | ︙ | |||
436 437 438 439 440 441 442 | return [expr {($n1 > $n2 ? $n1 : $n2) + 1}] } else { return [expr {-($n1 > $n2 ? $n1 : $n2)}] } } # Insert two blocks of lines in the compare windows. | < < | | > > | > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 | return [expr {($n1 > $n2 ? $n1 : $n2) + 1}] } else { return [expr {-($n1 > $n2 ? $n1 : $n2)}] } } # Insert two blocks of lines in the compare windows. proc insertMatchingBlocks {top block1 block2 line1 line2 details} { global doingLine1 doingLine2 # A large block may take time. Give a small warning. set n1 [llength $block1] set n2 [llength $block2] if {$n1 * $n2 > 1000} { set ::widgets($top,eqLabel) "!" #puts "Eskil warning: Analyzing a large block. ($size1 $size2)" update idletasks } # Detect if only newlines has changed within the block, e.g. # when rearranging newlines. if {$::eskil(ignorenewline)} { set res [ParseBlocksAcrossNewline $top $block1 $block2] if {$res != 0} { # FIXA: move this to ParseBlocksAcrossNewline ? if {$res > 0 && $details} { addChange $top $res change $line1 $n1 $line2 $n2 nextHighlight $top } else { addMapLines $top [expr {abs($res)}] } return } } set apa [compareBlocks $block1 $block2] # Fine grained changes means that each line is considered its own # chunk. This is used for merging better to avoid the same decision # for an entire block. set finegrain [expr {$::Pref(finegrainchunks) && $details}] if {$finegrain && $::diff($top,ancestorFile) ne ""} { # Avoid fine grain depending on relation to ancestor set leftChange 0 set leftChangeOrAdd 0 for {set t $line1} {$t < $line1 + $n1} {incr t} { if {[info exists ::diff($top,ancestorLeft,$t)]} { set leftChangeOrAdd 1 if {$::diff($top,ancestorLeft,$t) eq "c"} { set leftChange 1 break } } } set rightChange 0 set rightChangeOrAdd 0 for {set t $line2} {$t < $line2 + $n2} {incr t} { if {[info exists ::diff($top,ancestorRight,$t)]} { set rightChangeOrAdd 1 if {$::diff($top,ancestorRight,$t) eq "c"} { set rightChange 1 break } } } # Avoid fine grain if either side has no changes against ancestor if {!$leftChangeOrAdd || !$rightChangeOrAdd} { set finegrain 0 } # Avoid fine grain if both sides have at most additions if {!$leftChange && !$rightChange} { set finegrain 0 } } set t1 0 set t2 0 foreach c $apa { if {$c eq "c"} { set textline1 [lindex $block1 $t1] set textline2 [lindex $block2 $t2] insertMatchingLines $top $textline1 $textline2 if {$finegrain} { addChange $top 1 change [expr {$line1 + $t1}] 1 \ [expr {$line2 + $t2}] 1 nextHighlight $top } incr t1 incr t2 } elseif {$c eq "C"} { # This is two lines that the block matching considered # too different to use line parsing on them. # Marked the whole line as deleted/inserted set textline1 [lindex $block1 $t1] set textline2 [lindex $block2 $t2] $::widgets($top,wLine1) insert end [myFormL $doingLine1] \ "hl$::HighLightCount change" $::widgets($top,wDiff1) insert end "$textline1\n" new1 $::widgets($top,wLine2) insert end [myFormL $doingLine2] \ "hl$::HighLightCount change" $::widgets($top,wDiff2) insert end "$textline2\n" new2 if {$finegrain} { addChange $top 1 change [expr {$line1 + $t1}] 1 \ [expr {$line2 + $t2}] 1 nextHighlight $top } incr doingLine1 incr doingLine2 incr t1 incr t2 } elseif {$c eq "d"} { set bepa [lindex $block1 $t1] $::widgets($top,wLine1) insert end [myFormL $doingLine1] \ "hl$::HighLightCount change" $::widgets($top,wDiff1) insert end "$bepa\n" new1 emptyLine $top 2 incr doingLine1 if {$finegrain} { addChange $top 1 new1 [expr {$line1 + $t1}] 1 \ [expr {$line2 + $t2}] 0 nextHighlight $top } incr t1 } elseif {$c eq "a"} { set bepa [lindex $block2 $t2] $::widgets($top,wLine2) insert end [myFormL $doingLine2] \ "hl$::HighLightCount change" $::widgets($top,wDiff2) insert end "$bepa\n" new2 emptyLine $top 1 incr doingLine2 if {$finegrain} { addChange $top 1 new2 [expr {$line1 + $t1}] 0 \ [expr {$line2 + $t2}] 1 nextHighlight $top } incr t2 } } if {!$finegrain} { if {$details} { addChange $top [llength $apa] change $line1 $n1 $line2 $n2 nextHighlight $top } else { addMapLines $top [llength $apa] } } } # Process one of the change/add/delete blocks reported by diff. # ch1 is a file channel for the left file # ch2 is a file channel for the right file # n1/n2 is the number of lines involved # line1/line2 says on what lines this block starts |
︙ | ︙ | |||
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 | gets $ch2 textline2 insertMatchingLines $top $textline1 $textline2 } if {$::diff(filter) != "" && $::diff(filterflag)} { addMapLines $top $n1 } else { addChange $top $n1 change $line1 $n1 $line2 $n2 } } else { if {$n1 != 0 && $n2 != 0 && $Pref(parse) >= 2 && \ ($n1 * $n2 < 1000 || $Pref(parse) == 3)} { # Full block parsing set block1 {} for {set t 0} {$t < $n1} {incr t} { gets $ch1 apa lappend block1 $apa } set block2 {} for {set t 0} {$t < $n2} {incr t} { gets $ch2 apa lappend block2 $apa } | > | < < < < < < < > > | 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 | gets $ch2 textline2 insertMatchingLines $top $textline1 $textline2 } if {$::diff(filter) != "" && $::diff(filterflag)} { addMapLines $top $n1 } else { addChange $top $n1 change $line1 $n1 $line2 $n2 nextHighlight $top } } else { if {$n1 != 0 && $n2 != 0 && $Pref(parse) >= 2 && \ ($n1 * $n2 < 1000 || $Pref(parse) == 3)} { # Full block parsing set block1 {} for {set t 0} {$t < $n1} {incr t} { gets $ch1 apa lappend block1 $apa } set block2 {} for {set t 0} {$t < $n2} {incr t} { gets $ch2 apa lappend block2 $apa } insertMatchingBlocks $top $block1 $block2 $line1 $line2 1 } else { # No extra parsing at all. for {set t 0} {$t < $n1} {incr t} { gets $ch1 apa insertLine $top 1 $doingLine1 $apa $tag1 incr doingLine1 } for {set t 0} {$t < $n2} {incr t} { gets $ch2 apa insertLine $top 2 $doingLine2 $apa $tag2 incr doingLine2 } if {$n1 <= $n2} { for {set t $n1} {$t < $n2} {incr t} { emptyLine $top 1 } addChange $top $n2 $tag2 $line1 $n1 $line2 $n2 nextHighlight $top } elseif {$n2 < $n1} { for {set t $n2} {$t < $n1} {incr t} { emptyLine $top 2 } addChange $top $n1 $tag1 $line1 $n1 $line2 $n2 nextHighlight $top } } } # Empty return value return } |
︙ | ︙ | |||
874 875 876 877 878 879 880 | } continue } # No change block anymore. If one just ended, display it. if {[llength $lblock] > 0 || [llength $rblock] > 0} { set ::doingLine1 $lblockl set ::doingLine2 $rblockl | | | 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 | } continue } # No change block anymore. If one just ended, display it. if {[llength $lblock] > 0 || [llength $rblock] > 0} { set ::doingLine1 $lblockl set ::doingLine2 $rblockl insertMatchingBlocks $top $lblock $rblock $lblockl $rblockl 0 set lblock {} set rblock {} } if {$lmode == "" && $rmode == ""} { insertLine $top 1 $lline $lstr insertLine $top 2 $rline $rstr incr leftc |
︙ | ︙ | |||
905 906 907 908 909 910 911 | continue } } # If the patch ended with a change block, display it. if {[llength $lblock] > 0 || [llength $rblock] > 0} { set ::doingLine1 $lblockl set ::doingLine2 $rblockl | | > | > > > | 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 | continue } } # If the patch ended with a change block, display it. if {[llength $lblock] > 0 || [llength $rblock] > 0} { set ::doingLine1 $lblockl set ::doingLine2 $rblockl insertMatchingBlocks $top $lblock $rblock $lblockl $rblockl 0 set lblock {} set rblock {} } } # Read a patch file and display it proc displayPatch {top} { global Pref set ::diff($top,leftLabel) "Patch $::diff($top,patchFile): old" set ::diff($top,rightLabel) "Patch $::diff($top,patchFile): new" update idletasks if {$::diff($top,patchFile) eq ""} { if {$::diff($top,patchData) eq ""} { set data [getFullPatch $top] } else { set data $::diff($top,patchData) } } elseif {$::diff($top,patchFile) eq "-"} { set data [read stdin] } else { set ch [open $::diff($top,patchFile) r] set data [read $ch] close $ch } |
︙ | ︙ | |||
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 | # Restore view foreach item {wLine1 wDiff1 wLine2 wDiff2} { set w $::widgets($top,$item) seeText $w $first.0 $last.0 } } # Main diff function. proc doDiff {top} { global Pref global doingLine1 doingLine2 if {$::diff($top,mode) eq "" && ($::diff($top,leftOK) == 0 || $::diff($top,rightOK) == 0)} { | > > > > > > > > > > > > > > > > | 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 | # Restore view foreach item {wLine1 wDiff1 wLine2 wDiff2} { set w $::widgets($top,$item) seeText $w $first.0 $last.0 } } # Make an appropriate tail for a window title, depending on mode and files. proc TitleTail {top} { set tail1 [file tail $::diff($top,rightLabel)] set tail2 [file tail $::diff($top,leftLabel)] if {$::diff($top,mode) ne "" || $tail1 eq $tail2} { if {$::diff($top,mode) eq "rev"} { set tail1 [file tail $::diff($top,RevFile)] } elseif {$::diff($top,mode) eq "conflict"} { set tail1 [file tail $::diff($top,conflictFile)] } return $tail1 } else { return "$tail2 vs $tail1" } } # Main diff function. proc doDiff {top} { global Pref global doingLine1 doingLine2 if {$::diff($top,mode) eq "" && ($::diff($top,leftOK) == 0 || $::diff($top,rightOK) == 0)} { |
︙ | ︙ | |||
1198 1199 1200 1201 1202 1203 1204 | $::widgets($top,wLine2) see 1.0 normalCursor $top return } else { prepareFiles $top } | < < < < < < < < | < < < | 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 | $::widgets($top,wLine2) see 1.0 normalCursor $top return } else { prepareFiles $top } wm title $top "Eskil: [TitleTail $top]" # Run diff and parse the result. set opts $Pref(ignore) if {$Pref(nocase)} {lappend opts -nocase} if {$Pref(noempty)} {lappend opts -noempty} if {[info exists ::diff($top,aligns)] && \ [llength $::diff($top,aligns)] > 0} { |
︙ | ︙ | |||
1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 | return } } else { set ::widgets($top,eqLabel) " " } # Update the equal label immediately for better feedback update idletasks set firstview 1 set ch1 [open $::diff($top,leftFile)] set ch2 [open $::diff($top,rightFile)] set doingLine1 1 set doingLine2 1 | > > > > | 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 | return } } else { set ::widgets($top,eqLabel) " " } # Update the equal label immediately for better feedback update idletasks if {$::diff($top,ancestorFile) ne ""} { collectAncestorInfo $top $dFile1 $dFile2 $opts } set firstview 1 set ch1 [open $::diff($top,leftFile)] set ch2 [open $::diff($top,rightFile)] set doingLine1 1 set doingLine2 1 |
︙ | ︙ | |||
1293 1294 1295 1296 1297 1298 1299 | incr doingLine2 } } set t 0 foreach i $diffres { lassign $i line1 n1 line2 n2 | | < < < < < < < < < < | 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 | incr doingLine2 } } set t 0 foreach i $diffres { lassign $i line1 n1 line2 n2 doText $top $ch1 $ch2 $n1 $n2 $line1 $line2 if {$::diff($top,limitlines) && \ ($::diff($top,mapMax) > $::diff($top,limitlines))} { break } # Get one update when the screen has been filled. # Show the first diff. if {$firstview && $::diff($top,mapMax) > 100} { set firstview 0 showDiff $top 0 update idletasks } } # If there is a range, just display the range if {[llength $range] != 0} { lassign $range start1 end1 start2 end2 } else { set end1 0 |
︙ | ︙ | |||
1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 | set ::widgets($top,eqLabel) " " } cleanupFiles $top if {$::diff($top,mode) eq "conflict"} { if {$::widgets($top,eqLabel) != "="} { makeMergeWin $top } } if {$::diff($top,printFile) ne ""} { after idle "doPrint $top 1 ; cleanupAndExit all" } } | > > > > | 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 | set ::widgets($top,eqLabel) " " } cleanupFiles $top if {$::diff($top,mode) eq "conflict"} { if {$::widgets($top,eqLabel) != "="} { makeMergeWin $top } } elseif {$::diff($top,ancestorFile) ne ""} { if {$::widgets($top,eqLabel) != "="} { makeMergeWin $top } } if {$::diff($top,printFile) ne ""} { after idle "doPrint $top 1 ; cleanupAndExit all" } } |
︙ | ︙ | |||
1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 | set ::diff($top,rightFile) $apa set ::diff($top,rightLabel) $apa set ::diff($top,rightOK) 1 return 1 } return 0 } proc openLeft {top} { if {[doOpenLeft $top]} { set ::diff($top,mode) "" set ::diff($top,mergeFile) "" doDiff $top } } proc openRight {top} { if {[doOpenRight $top]} { set ::diff($top,mode) "" set ::diff($top,mergeFile) "" doDiff $top } } proc openConflict {top} { global Pref if {[doOpenRight $top]} { startConflictDiff $top $::diff($top,rightFile) set ::diff($top,mergeFile) "" doDiff $top } } proc openPatch {top} { global Pref if {[doOpenLeft $top]} { set ::diff($top,mode) "patch" set Pref(ignore) " " set Pref(nocase) 0 set Pref(noempty) 0 set ::diff($top,patchFile) $::diff($top,leftFile) doDiff $top } } proc openRev {top} { if {[doOpenRight $top]} { set rev [detectRevSystem $::diff($top,rightFile)] if {$rev eq ""} { tk_messageBox -icon error -title "Eskil Error" -message \ "Could not figure out which revison control system\ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 | set ::diff($top,rightFile) $apa set ::diff($top,rightLabel) $apa set ::diff($top,rightOK) 1 return 1 } return 0 } proc doOpenAncestor {top} { if {$::diff($top,ancestorFile) ne ""} { set initDir [file dirname $::diff($top,ancestorFile)] } elseif {[info exists ::diff($top,leftDir)]} { set initDir $::diff($top,leftDir) } elseif {[info exists ::diff($top,rightDir)]} { set initDir $::diff($top,rightDir) } else { set initDir [pwd] } set apa [myOpenFile -title "Select ancestor file" -initialdir $initDir \ -parent $top] if {$apa != ""} { set ::diff($top,ancestorFile) $apa return 1 } return 0 } proc openLeft {top} { if {[doOpenLeft $top]} { set ::diff($top,mode) "" set ::diff($top,mergeFile) "" doDiff $top } } proc openRight {top} { if {[doOpenRight $top]} { set ::diff($top,mode) "" set ::diff($top,mergeFile) "" doDiff $top } } proc openAncestor {top} { if {[doOpenAncestor $top]} { # Redo diff with ancestor doDiff $top } } proc openConflict {top} { global Pref if {[doOpenRight $top]} { startConflictDiff $top $::diff($top,rightFile) set ::diff($top,mergeFile) "" doDiff $top } } proc openPatch {top} { global Pref if {[doOpenLeft $top]} { set ::diff($top,mode) "patch" set Pref(ignore) " " set Pref(nocase) 0 set Pref(noempty) 0 set ::diff($top,patchFile) $::diff($top,leftFile) set ::diff($top,patchData) "" doDiff $top } } # Get data from clipboard and display as a patch. proc doPastePatch {top} { if {[catch {::tk::GetSelection $top CLIPBOARD} sel]} { tk_messageBox -icon error -title "Eskil Error" -parent $top \ -message "Could not retreive clipboard" -type ok return } set ::diff($top,mode) "patch" set ::Pref(ignore) " " set ::Pref(nocase) 0 set ::Pref(noempty) 0 set ::diff($top,patchFile) "" set ::diff($top,patchData) $sel doDiff $top } proc openRev {top} { if {[doOpenRight $top]} { set rev [detectRevSystem $::diff($top,rightFile)] if {$rev eq ""} { tk_messageBox -icon error -title "Eskil Error" -message \ "Could not figure out which revison control system\ |
︙ | ︙ | |||
2260 2261 2262 2263 2264 2265 2266 | if {!$tmp1 && $tmp2} {.lpm delete last} set ::diff($top,nopopup) 1 tk_popup .lpm $X $Y after idle [list after 1 [list set ::diff($top,nopopup) 0]] } | | > | 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 | if {!$tmp1 && $tmp2} {.lpm delete last} set ::diff($top,nopopup) 1 tk_popup .lpm $X $Y after idle [list after 1 [list set ::diff($top,nopopup) 0]] } proc nextHighlight {top} { set tag hl$::HighLightCount foreach n {1 2} { $::widgets($top,wLine$n) tag bind $tag <ButtonPress-3> \ "hlPopup $top $n $::HighLightCount %X %Y %x %y ; break" $::widgets($top,wLine$n) tag bind $tag <ButtonPress-1> \ "hlSelect $top $::HighLightCount" } incr ::HighLightCount } ######### # Zooming ######### proc zoomRow {w X Y x y} { |
︙ | ︙ | |||
2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 | proc applyColor {} { global dirdiff Pref foreach top $::diff(diffWindows) { if {$top eq ".clipdiff"} continue if {$top != ".dirdiff"} { foreach item {wLine1 wDiff1 wLine2 wDiff2} { set w $::widgets($top,$item) $w tag configure equal -foreground $Pref(colorequal) \ -background $Pref(bgequal) $w tag configure new1 -foreground $Pref(colornew1) \ -background $Pref(bgnew1) $w tag configure change -foreground $Pref(colorchange) \ | > | 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 | proc applyColor {} { global dirdiff Pref foreach top $::diff(diffWindows) { if {$top eq ".clipdiff"} continue if {$top != ".dirdiff"} { foreach item {wLine1 wDiff1 wLine2 wDiff2} { if {![info exists ::widgets($top,$item)]} continue set w $::widgets($top,$item) $w tag configure equal -foreground $Pref(colorequal) \ -background $Pref(bgequal) $w tag configure new1 -foreground $Pref(colornew1) \ -background $Pref(bgnew1) $w tag configure change -foreground $Pref(colorchange) \ |
︙ | ︙ | |||
2429 2430 2431 2432 2433 2434 2435 | # Do not scroll if focus is in a text window. # This is for scroll bindings in the toplevel. if {[winfo class [focus]] != "Text"} { $::widgets($top,wDiff1) yview scroll $n $what } } | < < < < < < < < | 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 | # Do not scroll if focus is in a text window. # This is for scroll bindings in the toplevel. if {[winfo class [focus]] != "Text"} { $::widgets($top,wDiff1) yview scroll $n $what } } # Emulate a label that: # 1 : Displays the right part of the text if there isn't enough room # 2 : Justfify text to the left if there is enough room. # 3 : Does not try to allocate space according to its contents proc fileLabel {w args} { ttk::entryX $w -style TLabel $w configure {*}$args |
︙ | ︙ | |||
2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 | # Fill in default data for a diff window proc initDiffData {top} { set ::diff($top,leftOK) 0 set ::diff($top,rightOK) 0 set ::diff($top,mode) "" set ::diff($top,printFile) "" set ::diff($top,mergeFile) "" set ::diff($top,conflictFile) "" set ::diff($top,limitlines) 0 set ::diff($top,plugin) "" } # Create a new diff window and diff two files proc newDiff {file1 file2 {range {}}} { | > | 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 | # Fill in default data for a diff window proc initDiffData {top} { set ::diff($top,leftOK) 0 set ::diff($top,rightOK) 0 set ::diff($top,mode) "" set ::diff($top,printFile) "" set ::diff($top,mergeFile) "" set ::diff($top,ancestorFile) "" set ::diff($top,conflictFile) "" set ::diff($top,limitlines) 0 set ::diff($top,plugin) "" } # Create a new diff window and diff two files proc newDiff {file1 file2 {range {}}} { |
︙ | ︙ | |||
2513 2514 2515 2516 2517 2518 2519 | } # A thing to easily get to debug mode proc backDoor {a} { append ::eskil(backdoor) $a set ::eskil(backdoor) [string range $::eskil(backdoor) end-9 end] if {$::eskil(backdoor) eq "PeterDebug"} { | | | | | > > | 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 | } # A thing to easily get to debug mode proc backDoor {a} { append ::eskil(backdoor) $a set ::eskil(backdoor) [string range $::eskil(backdoor) end-9 end] if {$::eskil(backdoor) eq "PeterDebug"} { set ::eskil(debug) 1 catch {console show} set ::eskil(backdoor) "" } } # Build the main window proc makeDiffWin {{top {}}} { global Pref tcl_platform if {$top != "" && [winfo exists $top] && [winfo toplevel $top] eq $top} { # Reuse the old window destroy {*}[winfo children $top] } else { # Locate a free toplevel name if {[info exists ::diff(topDiffCnt)]} { set t $::diff(topDiffCnt) } else { set t 0 } while {[winfo exists .diff$t]} { incr t } set top .diff$t toplevel $top eskilRegisterToplevel $top } wm title $top "Eskil:" wm protocol $top WM_DELETE_WINDOW [list cleanupAndExit $top] ttk::frame $top.f grid $top.f -row 0 -columnspan 4 -sticky nws lappend ::widgets(toolbars) $top.f if {!$::Pref(toolbar)} { grid remove $top.f } menu $top.m $top configure -menu $top.m $top.m add cascade -label "File" -underline 0 -menu $top.m.mf menu $top.m.mf $top.m.mf add command -label "Redo Diff" -underline 5 \ -command [list redoDiff $top] -state disabled if {$::eskil(debug) == 1} { $top.m.mf entryconfigure "Redo Diff" -state normal } $top.m.mf add separator $top.m.mf add command -label "Open Both..." -underline 0 \ -command [list openBoth $top 0] $top.m.mf add command -label "Open Both (forget)..." \ -command [list openBoth $top 1] $top.m.mf add command -label "Open Left File..." \ -command [list openLeft $top] $top.m.mf add command -label "Open Right File..." \ -command [list openRight $top] $top.m.mf add separator $top.m.mf add command -label "Open Ancestor File..." \ -command [list openAncestor $top] $top.m.mf add command -label "Open Conflict File..." \ -command [list openConflict $top] $top.m.mf add command -label "Open Patch File..." \ -command [list openPatch $top] $top.m.mf add command -label "Revision Diff..." -underline 0 \ -command [list openRev $top] $top.m.mf add separator |
︙ | ︙ | |||
2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 | $top.m add cascade -label "Options" -underline 0 -menu $top.m.mo menu $top.m.mo $top.m.mo add cascade -label "Font" -underline 0 -menu $top.m.mo.f $top.m.mo add cascade -label "Ignore" -underline 0 -menu $top.m.mo.i $top.m.mo add command -label "Preprocess..." -underline 0 \ -command [list EditPrefRegsub $top] $top.m.mo add cascade -label "Parse" -underline 1 -menu $top.m.mo.p $top.m.mo add command -label "Colours..." -underline 0 -command makePrefWin $top.m.mo add cascade -label "Context" -underline 1 -menu $top.m.mo.c $top.m.mo add separator $top.m.mo add checkbutton -label "Toolbar" -variable ::Pref(toolbar) $top.m.mo add separator $top.m.mo add command -label "Save default" \ | > > | 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 | $top.m add cascade -label "Options" -underline 0 -menu $top.m.mo menu $top.m.mo $top.m.mo add cascade -label "Font" -underline 0 -menu $top.m.mo.f $top.m.mo add cascade -label "Ignore" -underline 0 -menu $top.m.mo.i $top.m.mo add command -label "Preprocess..." -underline 0 \ -command [list EditPrefRegsub $top] $top.m.mo add command -label "Plugins..." -underline 1 \ -command [list EditPrefPlugins $top] $top.m.mo add cascade -label "Parse" -underline 1 -menu $top.m.mo.p $top.m.mo add command -label "Colours..." -underline 0 -command makePrefWin $top.m.mo add cascade -label "Context" -underline 1 -menu $top.m.mo.c $top.m.mo add separator $top.m.mo add checkbutton -label "Toolbar" -variable ::Pref(toolbar) $top.m.mo add separator $top.m.mo add command -label "Save default" \ |
︙ | ︙ | |||
2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 | $top.m.mo.p add radiobutton -label "Blocks" -variable Pref(parse) -value 3 $top.m.mo.p add separator $top.m.mo.p add radiobutton -label "Characters" \ -variable Pref(lineparsewords) -value "0" $top.m.mo.p add radiobutton -label "Words" \ -variable Pref(lineparsewords) -value "1" $top.m.mo.p add separator $top.m.mo.p add checkbutton -label "Mark last" -variable Pref(marklast) menu $top.m.mo.c $top.m.mo.c add radiobutton -label "Show all lines" \ -variable ::Pref(context) -value -1 $top.m.mo.c add radiobutton -label "Show only diffs" \ -variable ::Pref(context) -value 0 | > > | 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 | $top.m.mo.p add radiobutton -label "Blocks" -variable Pref(parse) -value 3 $top.m.mo.p add separator $top.m.mo.p add radiobutton -label "Characters" \ -variable Pref(lineparsewords) -value "0" $top.m.mo.p add radiobutton -label "Words" \ -variable Pref(lineparsewords) -value "1" $top.m.mo.p add separator $top.m.mo.p add checkbutton -label "Fine chunks" -variable Pref(finegrainchunks) $top.m.mo.p add separator $top.m.mo.p add checkbutton -label "Mark last" -variable Pref(marklast) menu $top.m.mo.c $top.m.mo.c add radiobutton -label "Show all lines" \ -variable ::Pref(context) -value -1 $top.m.mo.c add radiobutton -label "Show only diffs" \ -variable ::Pref(context) -value 0 |
︙ | ︙ | |||
2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 | -command makeDirDiffWin $top.m.mt add command -label "Clip Diff" -underline 0 \ -command makeClipDiffWin $top.m.mt add command -label "Merge" -underline 0 \ -command [list makeMergeWin $top] -state disabled $top.m.mt add command -label "Edit Mode" -underline 0 \ -command [list allowEdit $top] -state disabled $top.m.mt add command -label "Clear Align" \ -command [list clearAlign $top] -state disabled set ::widgets($top,enableAlignCmd) [list \ $top.m.mt entryconfigure "Clear Align" -state normal] set ::widgets($top,disableAlignCmd) [list \ $top.m.mt entryconfigure "Clear Align" -state disabled] | > > | 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 | -command makeDirDiffWin $top.m.mt add command -label "Clip Diff" -underline 0 \ -command makeClipDiffWin $top.m.mt add command -label "Merge" -underline 0 \ -command [list makeMergeWin $top] -state disabled $top.m.mt add command -label "Edit Mode" -underline 0 \ -command [list allowEdit $top] -state disabled $top.m.mt add command -label "Paste Patch" -underline 0 \ -command [list doPastePatch $top] $top.m.mt add command -label "Clear Align" \ -command [list clearAlign $top] -state disabled set ::widgets($top,enableAlignCmd) [list \ $top.m.mt entryconfigure "Clear Align" -state normal] set ::widgets($top,disableAlignCmd) [list \ $top.m.mt entryconfigure "Clear Align" -state disabled] |
︙ | ︙ | |||
2831 2832 2833 2834 2835 2836 2837 | grid $top.ls -sticky "" bind $top <Key-Up> [list scrollText $top -1 u] bind $top <Key-Down> [list scrollText $top 1 u] bind $top <Key-Prior> [list scrollText $top -1 pa] bind $top <Key-Next> [list scrollText $top 1 pa] bind $top <Key-Escape> [list focus $top] | | | | 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 | grid $top.ls -sticky "" bind $top <Key-Up> [list scrollText $top -1 u] bind $top <Key-Down> [list scrollText $top 1 u] bind $top <Key-Prior> [list scrollText $top -1 pa] bind $top <Key-Next> [list scrollText $top 1 pa] bind $top <Key-Escape> [list focus $top] if {$::eskil(debug) == 0} { bind $top <Key> "backDoor %A" } pack $top.bfn -in $top.f -side right -padx {3 6} pack $top.bfp $top.bcm $top.blg \ $top.er2 $top.lr2 $top.er1 $top.lr1 \ -in $top.f -side right -padx 3 pack $top.bfn $top.bfp $top.bcm -ipadx 15 if {$::eskil(debug) == 1} { $top.m add cascade -label "Debug" -menu $top.m.md -underline 0 menu $top.m.md if {$tcl_platform(platform) eq "windows"} { $top.m.md add checkbutton -label "Console" -variable consolestate \ -onvalue show -offvalue hide \ -command {console $consolestate} $top.m.md add separator |
︙ | ︙ | |||
3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 | -prefix <str> : Care mainly about words starting with "str". -preprocess <pair> : TBW -r <ver> : Version info for version control mode. -cvs : Detect CVS first, if multiple version systems are used. -svn : Detect SVN first, if multiple version systems are used. -conflict : Treat file as a merge conflict file and enter merge mode. -o <file> : Specify merge result output file. -browse : Automatically bring up file dialog after starting. -server : Set up Eskil to be controllable from the outside. | > > | > > > > > > | > | 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 | -prefix <str> : Care mainly about words starting with "str". -preprocess <pair> : TBW -r <ver> : Version info for version control mode. -cvs : Detect CVS first, if multiple version systems are used. -svn : Detect SVN first, if multiple version systems are used. -a <file> : Give anscestor file for three way merge. -conflict : Treat file as a merge conflict file and enter merge mode. -o <file> : Specify merge result output file. -fine : Use fine grained chunks. Useful for merging. -browse : Automatically bring up file dialog after starting. -server : Set up Eskil to be controllable from the outside. -print <file> : Generate PDF and exit. -printCharsPerLine <n> : Adapt font size for this line length and wrap. (80) -printPaper <paper> : Select paper size (a4) -printHeaderSize <n> : Font size for page header (10) -printColorChange <RGB> : Color for change (1.0 0.7 0.7) -printColorOld <RGB> : Color for old text (0.7 1.0 0.7) -printColorNew <RGB : Color for new text (0.8 0.8 1.0) -plugin <name> : Preprocess files using plugin. -plugininfo <info> : Pass info to plugin (plugin specific) -pluginlist : List known plugins -plugindump <plugin> : Dump plugin source to stdout -limit <lines> : Do not process more than <lines> lines. To list all options matching a prefix, run 'eskil --query prefix'. In tcsh use this line to get option completion: complete eskil 'C/-/`eskil --query -`/'} |
︙ | ︙ | |||
3398 3399 3400 3401 3402 3403 3404 | } if {$fail} { puts "Argument $opt must be a list of RBG values from 0.0 to 1.0" exit } } | | > > > > | < | | | 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 | } if {$fail} { puts "Argument $opt must be a list of RBG values from 0.0 to 1.0" exit } } # Go through all command line arguments and start the appropriate # diff window. # Returns the created toplevel. # This can be used as an entry point if embedding eskil. # In that case fill in ::eskil(argv) and ::eskil(argc) before calling. proc parseCommandLine {} { global dirdiff Pref set ::eskil(autoclose) 0 set ::eskil(ignorenewline) 0 if {$::eskil(argc) == 0} { Init return [makeDiffWin] } set allOpts { -w --help -help -b -noignore -i -nocase -nodigit -nokeyword -prefix -noparse -line -smallblock -block -char -word -limit -nodiff -dir -clip -patch -browse -conflict -print -printHeaderSize -printCharsPerLine -printPaper -printColorChange -printColorOld -printColorNew -server -o -a -fine -r -context -cvs -svn -review -foreach -preprocess -close -nonewline -plugin -plugininfo -plugindump -pluginlist } # If the first option is "--query", use it to ask about options. if {$::eskil(argc) == 2 && [lindex $::eskil(argv) 0] == "--query"} { set arg [lindex $::eskil(argv) 1] if {[lsearch -exact $allOpts $arg] < 0} { set match [lsearch -glob -all -inline $allOpts $arg*] |
︙ | ︙ | |||
3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 | set dopatch 0 set doreview 0 set foreach 0 set preferedRev "GIT" set plugin "" set plugininfo "" set plugindump "" foreach arg $::eskil(argv) { if {$nextArg != ""} { if {$nextArg eq "mergeFile"} { set opts(mergeFile) [file join [pwd] $arg] } elseif {$nextArg eq "printFile"} { set opts(printFile) [file join [pwd] $arg] } elseif {$nextArg eq "printHeaderSize"} { if {![string is double -strict $arg] || $arg <= 0} { puts "Argument -printHeaderSize must be a positive number" exit } | > > > | 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 | set dopatch 0 set doreview 0 set foreach 0 set preferedRev "GIT" set plugin "" set plugininfo "" set plugindump "" set pluginlist 0 foreach arg $::eskil(argv) { if {$nextArg != ""} { if {$nextArg eq "mergeFile"} { set opts(mergeFile) [file join [pwd] $arg] } elseif {$nextArg eq "ancestorFile"} { set opts(ancestorFile) [file join [pwd] $arg] } elseif {$nextArg eq "printFile"} { set opts(printFile) [file join [pwd] $arg] } elseif {$nextArg eq "printHeaderSize"} { if {![string is double -strict $arg] || $arg <= 0} { puts "Argument -printHeaderSize must be a positive number" exit } |
︙ | ︙ | |||
3559 3560 3561 3562 3563 3564 3565 | } elseif {$arg eq "-nokeyword"} { set Pref(dir,ignorekey) 1 } elseif {$arg eq "-prefix"} { set nextArg prefix } elseif {$arg eq "-preprocess"} { set nextArg preprocess } elseif {$arg eq "-plugin"} { | | | | > > | 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 | } elseif {$arg eq "-nokeyword"} { set Pref(dir,ignorekey) 1 } elseif {$arg eq "-prefix"} { set nextArg prefix } elseif {$arg eq "-preprocess"} { set nextArg preprocess } elseif {$arg eq "-plugin"} { set nextArg "plugin" } elseif {$arg eq "-plugininfo"} { set nextArg "plugininfo" } elseif {$arg eq "-plugindump"} { set nextArg "plugindump" } elseif {$arg eq "-pluginlist"} { set pluginlist 1 } elseif {$arg eq "-context"} { set nextArg context } elseif {$arg eq "-noparse"} { set Pref(parse) 0 } elseif {$arg eq "-line"} { set Pref(parse) 1 } elseif {$arg eq "-smallblock"} { |
︙ | ︙ | |||
3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 | set ::eskil(ignorenewline) 1 } elseif {$arg eq "-nonewline+"} { set ::eskil(ignorenewline) 2 } elseif {$arg eq "-close"} { set ::eskil(autoclose) 1 } elseif {$arg eq "-conflict"} { set opts(mode) "conflict" } elseif {$arg eq "-print" || $arg eq "-printpdf"} { set nextArg printFile } elseif {$arg in {-printHeaderSize -printCharsPerLine -printPaper \ -printColorChange -printColorOld -printColorNew}} { set nextArg [string range $arg 1 end] } elseif {$arg eq "-server"} { if {$::tcl_platform(platform) eq "windows"} { catch { package require dde dde servername Eskil } } else { package require Tk tk appname Eskil } } elseif {$arg eq "-o"} { set nextArg mergeFile } elseif {$arg eq "-r"} { set nextArg revision } elseif {$arg eq "-debug"} { | > > > > > > > > | > > > > > > | < | < | < | < | < > > > > > > > > > > > | < | 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 | set ::eskil(ignorenewline) 1 } elseif {$arg eq "-nonewline+"} { set ::eskil(ignorenewline) 2 } elseif {$arg eq "-close"} { set ::eskil(autoclose) 1 } elseif {$arg eq "-conflict"} { set opts(mode) "conflict" # Conflict implies foreach set foreach 1 } elseif {$arg eq "-print" || $arg eq "-printpdf"} { set nextArg printFile } elseif {$arg in {-printHeaderSize -printCharsPerLine -printPaper \ -printColorChange -printColorOld -printColorNew}} { set nextArg [string range $arg 1 end] } elseif {$arg eq "-server"} { if {$::tcl_platform(platform) eq "windows"} { catch { package require dde dde servername Eskil } } else { package require Tk tk appname Eskil } } elseif {$arg eq "-o"} { set nextArg mergeFile } elseif {$arg eq "-a"} { set nextArg ancestorFile # Default is no ignore on three-way merge set Pref(ignore) " " } elseif {$arg eq "-fine"} { set Pref(finegrainchunks) 1 } elseif {$arg eq "-r"} { set nextArg revision } elseif {$arg eq "-debug"} { set ::eskil(debug) 1 } elseif {$arg eq "-svn"} { set preferedRev "SVN" } elseif {$arg eq "-cvs"} { set preferedRev "CVS" } elseif {$arg eq "-"} { # Allow "-" for stdin patch processing lappend files "-" } else { set apa [file normalize [file join [pwd] $arg]] if {![file exists $apa]} { puts "Bad argument: $arg" exit } else { lappend files $apa } } } Init if {$pluginlist} { printPlugins exit } if {$plugindump ne ""} { printPlugin $plugindump exit } if {$plugin ne ""} { set pinterp [createPluginInterp $plugin $plugininfo] if {$pinterp eq ""} { puts "Bad plugin: $plugin" printPlugins exit } set opts(plugin) $pinterp set opts(pluginname) $plugin set opts(plugininfo) $plugininfo } # Do we start in clip diff mode? if {$doclip} { return [makeClipDiffWin] } # Figure out if we start in a diff or dirdiff window. set len [llength $files] if {$len == 0 && $dodir} { set dirdiff(leftDir) [pwd] set dirdiff(rightDir) [pwd] return [makeDirDiffWin] } if {$len == 1} { set fullname [lindex $files 0] if {[FileIsDirectory $fullname 1]} { set dirdiff(leftDir) $fullname set dirdiff(rightDir) $dirdiff(leftDir) return [makeDirDiffWin] } } elseif {$len >= 2} { set fullname1 [lindex $files 0] set fullname2 [lindex $files 1] if {[FileIsDirectory $fullname1 1] && [FileIsDirectory $fullname2 1]} { set dirdiff(leftDir) $fullname1 set dirdiff(rightDir) $fullname2 return [makeDirDiffWin] } } # Ok, we have a normal diff set top [makeDiffWin] update # Copy the previously collected options foreach {item val} [array get opts] { set ::diff($top,$item) $val } # It is preferable to see the end if the rev string is too long $::widgets($top,rev1) xview end $::widgets($top,rev2) xview end if {$doreview} { set rev [detectRevSystem "" $preferedRev] set ::diff($top,modetype) $rev set ::diff($top,mode) "patch" set ::diff($top,patchFile) "" set ::diff($top,patchData) "" set ::diff($top,reviewFiles) $files set ::Pref(toolbar) 1 after idle [list doDiff $top] return $top } if {$len == 1 || $foreach} { set ReturnAfterLoop 0 set first 1 foreach file $files { if {$first} { set first 0 } else { # Create new window for other files set top [makeDiffWin] update # Copy the previously collected options foreach {item val} [array get opts] { set ::diff($top,$item) $val } # It is preferable to see the end if the rev string is too long $::widgets($top,rev1) xview end $::widgets($top,rev2) xview end |
︙ | ︙ | |||
3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 | set ::diff($top,leftLabel) $fullname set ::diff($top,leftOK) 1 if {$dopatch || \ [regexp {\.(diff|patch)$} $fullname] || \ $fullname eq "-"} { set ::diff($top,mode) "patch" set ::diff($top,patchFile) $fullname set autobrowse 0 if {$noautodiff} { enableRedo $top } else { after idle [list doDiff $top] } set ReturnAfterLoop 1 continue } } | > | < < < < < < < < | 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 | set ::diff($top,leftLabel) $fullname set ::diff($top,leftOK) 1 if {$dopatch || \ [regexp {\.(diff|patch)$} $fullname] || \ $fullname eq "-"} { set ::diff($top,mode) "patch" set ::diff($top,patchFile) $fullname set ::diff($top,patchData) "" set autobrowse 0 if {$noautodiff} { enableRedo $top } else { after idle [list doDiff $top] } set ReturnAfterLoop 1 continue } } if {$ReturnAfterLoop} {return $top} } elseif {$len >= 2} { set fullname [file join [pwd] [lindex $files 0]] set fulldir [file dirname $fullname] set ::diff($top,leftDir) $fulldir set ::diff($top,leftFile) $fullname set ::diff($top,leftLabel) $fullname set ::diff($top,leftOK) 1 set fullname [file join [pwd] [lindex $files 1]] set fulldir [file dirname $fullname] set ::diff($top,rightDir) $fulldir set ::diff($top,rightFile) $fullname set ::diff($top,rightLabel) $fullname set ::diff($top,rightOK) 1 if {$noautodiff} { enableRedo $top } else { after idle [list doDiff $top] } } if {$autobrowse && (!$::diff($top,leftOK) || !$::diff($top,rightOK))} { if {!$::diff($top,leftOK) && !$::diff($top,rightOK)} { openBoth $top 0 } elseif {!$::diff($top,leftOK)} { openLeft $top } elseif {!$::diff($top,rightOK)} { openRight $top |
︙ | ︙ | |||
3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 | set fullname $::diff($top,leftFile) set ::diff($top,leftOK) 0 startRevMode $top "CVS" $fullname after idle [list doDiff $top] } } } } # Save options to file ~/.eskilrc proc saveOptions {top} { global Pref # Check if the window size has changed | > | 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 | set fullname $::diff($top,leftFile) set ::diff($top,leftOK) 0 startRevMode $top "CVS" $fullname after idle [list doDiff $top] } } } return $top } # Save options to file ~/.eskilrc proc saveOptions {top} { global Pref # Check if the window size has changed |
︙ | ︙ | |||
3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 | set Pref(colornew1) darkgreen set Pref(colornew2) blue set Pref(bgequal) "" set Pref(bgchange) \#ffe0e0 set Pref(bgnew1) \#a0ffa0 set Pref(bgnew2) \#e0e0ff set Pref(context) -1 set Pref(marklast) 1 set Pref(linewidth) 80 set Pref(lines) 60 set Pref(editor) "" set Pref(regsub) {} set Pref(toolbar) 0 set Pref(wideMap) 0 ;# Not settable in GUI yet | > | 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 | set Pref(colornew1) darkgreen set Pref(colornew2) blue set Pref(bgequal) "" set Pref(bgchange) \#ffe0e0 set Pref(bgnew1) \#a0ffa0 set Pref(bgnew2) \#e0e0ff set Pref(context) -1 set Pref(finegrainchunks) 0 set Pref(marklast) 1 set Pref(linewidth) 80 set Pref(lines) 60 set Pref(editor) "" set Pref(regsub) {} set Pref(toolbar) 0 set Pref(wideMap) 0 ;# Not settable in GUI yet |
︙ | ︙ | |||
3940 3941 3942 3943 3944 3945 3946 | } unset Pref(onlydiffs) # Set up reactions to some Pref settings if {![info exists ::widgets(toolbars)]} { set ::widgets(toolbars) {} } | < | > > > > | | | | | | | < | | | 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 | } unset Pref(onlydiffs) # Set up reactions to some Pref settings if {![info exists ::widgets(toolbars)]} { set ::widgets(toolbars) {} } trace add variable ::Pref(toolbar) write TraceToolbar } proc TraceToolbar {args} { # FIXA: Handle destroyed windows ? foreach __ $::widgets(toolbars) { if {$::Pref(toolbar)} { grid configure $__ } else { grid remove $__ } } } # Global code is only run the first time to be able to reread source if {![info exists ::eskil(gurkmeja)]} { set ::eskil(gurkmeja) 1 package require pstools namespace import -force pstools::* getOptions if {![info exists ::eskil_testsuite]} { parseCommandLine } } |
Changes to src/help.tcl.
︙ | ︙ | |||
21 22 23 24 25 26 27 | #---------------------------------------------------------------------- # $Revision$ #---------------------------------------------------------------------- # Silly experiment... proc makeNuisance {top {str {Hi there!}}} { if {[lsearch [image names] nuisance] < 0} { | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #---------------------------------------------------------------------- # $Revision$ #---------------------------------------------------------------------- # Silly experiment... proc makeNuisance {top {str {Hi there!}}} { if {[lsearch [image names] nuisance] < 0} { set file [file join $::eskil(thisDir) .. Nuisance.gif] if {![file exists $file]} return image create photo nuisance -file $file } destroy $top.nui toplevel $top.nui wm transient $top.nui $top |
︙ | ︙ | |||
68 69 70 71 72 73 74 | pack $w.b -side bottom -pady 2 pack $w.f -side top -expand y -fill both -padx 2 -pady 2 focus $w return $w.f } proc makeAboutWin {} { | < < | | < < < | | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | pack $w.b -side bottom -pady 2 pack $w.f -side top -expand y -fill both -padx 2 -pady 2 focus $w return $w.f } proc makeAboutWin {} { set w [helpWin .ab "About Eskil"] set bg [ttk::style configure . -background] text $w.t -width 45 -height 11 -wrap none -relief flat \ -background $bg pack $w.t -side top -expand y -fill both $w.t insert end "A graphical frontend to diff\n\n" $w.t insert end "$::eskil(diffver)\n\n" $w.t insert end "Made by Peter Spjuth\n" $w.t insert end "E-Mail: peter.spjuth@gmail.com\n" $w.t insert end "\nURL: http://eskil.berlios.de\n" $w.t insert end "\nTcl version: [info patchlevel]\n" set du $::DiffUtil::version append du " ($::DiffUtil::implementation)" $w.t insert end "DiffUtil version: $du\n" $w.t insert end "\nCredits:\n" $w.t insert end "Ideas for scrollbar map and merge function\n" $w.t insert end "taken from TkDiff" set last [lindex [split [$w.t index end] "."] 0] $w.t configure -height $last |
︙ | ︙ | |||
132 133 134 135 136 137 138 | } } } proc makeHelpWin {} { global Pref | | | 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | } } } proc makeHelpWin {} { global Pref set doc [file join $::eskil(thisDir) .. doc/eskil.txt] if {![file exists $doc]} return set w [helpWin .he "Eskil Help"] set t [Scroll y text $w.t -width 85 -height 35] pack $w.t -side top -expand 1 -fill both configureDocWin $t |
︙ | ︙ | |||
196 197 198 199 200 201 202 | proc makeDocWin {fileName} { set w [helpWin .doc "Eskil Help"] set t [Scroll y text $w.t -width 80 -height 25] pack $w.t -side top -expand 1 -fill both configureDocWin $t | | | | | | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | proc makeDocWin {fileName} { set w [helpWin .doc "Eskil Help"] set t [Scroll y text $w.t -width 80 -height 25] pack $w.t -side top -expand 1 -fill both configureDocWin $t if {![file exists $::eskil(thisDir)/../doc/$fileName]} { $t insert end "ERROR: Could not find doc file " $t insert end \"$fileName\" return } insertTaggedText $t $::eskil(thisDir)/../doc/$fileName #focus $t $t configure -state disabled } proc makeTutorialWin {} { global Pref set doc [file join $::eskil(thisDir) .. doc/tutorial.txt] if {![file exists $doc]} return if {[catch {cd [file join $::eskil(thisDir) .. examples]}]} { tk_messageBox -icon error -title "Eskil Error" -message \ "Could not locate examples directory." \ -type ok return } #set ::diff(tutorial) 1 |
︙ | ︙ |
Changes to src/merge.tcl.
1 2 3 | #---------------------------------------------------------------------- # Eskil, Merge function # | | < < > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #---------------------------------------------------------------------- # Eskil, Merge function # # Copyright (c) 1998-2011, Peter Spjuth (peter.spjuth@gmail.com) # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # #---------------------------------------------------------------------- # Get all data from the files to merge proc collectMergeData {top} { global diff set diff($top,leftMergeData) {} set diff($top,rightMergeData) {} set diff($top,mergeSelection,AnyConflict) 0 if {![info exists ::diff($top,changes)]} { set ::diff($top,changes) {} } prepareFiles $top |
︙ | ︙ | |||
67 68 69 70 71 72 73 | for {set t 0} {$t < $n2} {incr t} { gets $ch2 apa append data2 $apa\n incr doingLine2 } lappend diff($top,leftMergeData) $data1 lappend diff($top,rightMergeData) $data2 | | > > > > > > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | for {set t 0} {$t < $n2} {incr t} { gets $ch2 apa append data2 $apa\n incr doingLine2 } lappend diff($top,leftMergeData) $data1 lappend diff($top,rightMergeData) $data2 set diff($top,mergeSelection,$changeNo) \ [WhichSide $top $line1 $n1 $line2 $n2 conflict comment] set diff($top,mergeSelection,Conflict,$changeNo) $conflict set diff($top,mergeSelection,Comment,$changeNo) $comment if {$conflict} { set diff($top,mergeSelection,AnyConflict) 1 } incr changeNo } set data1 {} set data2 {} while {[gets $ch1 apa] != -1} { append data1 $apa\n incr doingLine1 |
︙ | ︙ | |||
97 98 99 100 101 102 103 104 105 106 107 108 109 | proc fillMergeWindow {top} { global diff set w $top.merge.t $w delete 1.0 end set marks {} set t 0 foreach {commLeft diffLeft} $diff($top,leftMergeData) \ {commRight diffRight} $diff($top,rightMergeData) { $w insert end $commRight if {![info exists diff($top,mergeSelection,$t)]} continue $w mark set merges$t insert $w mark gravity merges$t left | > > > > > | > > > > > > > > > < > > > > > > > > > > > | | | | | > > > > > > > > > > > > > > > > > > > > > > > | | < > > > | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | proc fillMergeWindow {top} { global diff set w $top.merge.t $w delete 1.0 end set marks {} set t 0 set firstConflict -1 foreach {commLeft diffLeft} $diff($top,leftMergeData) \ {commRight diffRight} $diff($top,rightMergeData) { $w insert end $commRight if {![info exists diff($top,mergeSelection,$t)]} continue $w mark set merges$t insert $w mark gravity merges$t left switch $diff($top,mergeSelection,$t) { 1 { $w insert end $diffLeft merge$t } 2 { $w insert end $diffRight merge$t } 12 { $w insert end $diffLeft merge$t $w insert end $diffRight merge$t } 21 { $w insert end $diffRight merge$t $w insert end $diffLeft merge$t } } if {$diff($top,mergeSelection,Conflict,$t)} { $w tag configure merge$t -background grey if {$firstConflict == -1} { set firstConflict $t } } lappend marks mergee$t [$w index insert] incr t } foreach {mark index} $marks { $w mark set $mark $index } # Add fences to simplify some handling later $w mark set mergee-2 1.0 $w mark set mergee-1 1.0 $w mark set merges$t end $w mark set merges[expr {$t + 1}] end set showFirst 0 if {$firstConflict != -1} { set showFirst $firstConflict } set diff($top,curMerge) $showFirst set diff($top,curMergeSel) $diff($top,mergeSelection,$showFirst) $w tag configure merge$showFirst -foreground red showDiff $top $showFirst update # If there is any diff, show the first if {$t > 0} { seeText $w merges$showFirst mergee$showFirst # Show status for first chunk set diff($top,mergeStatus) \ $diff($top,mergeSelection,Comment,$showFirst) } } # Move to and highlight another diff. proc nextMerge {top delta} { global diff set w $top.merge.t $w tag configure merge$diff($top,curMerge) -foreground "" set last [expr {[llength $diff($top,leftMergeData)] / 2 - 1}] if {$delta == -1000} { # Search backward for conflict for {set t [expr {$diff($top,curMerge) - 1}]} {$t >= 0} {incr t -1} { if {$diff($top,mergeSelection,Conflict,$t)} { set delta [expr {$t - $diff($top,curMerge)}] break } } } elseif {$delta == 1000} { # Search forward for conflict for {set t [expr {$diff($top,curMerge) + 1}]} {$t <= $last} {incr t} { if {$diff($top,mergeSelection,Conflict,$t)} { set delta [expr {$t - $diff($top,curMerge)}] break } } } set diff($top,curMerge) [expr {$diff($top,curMerge) + $delta}] if {$diff($top,curMerge) < 0} {set diff($top,curMerge) 0} if {$diff($top,curMerge) > $last} { set diff($top,curMerge) $last } set diff($top,curMergeSel) $diff($top,mergeSelection,$diff($top,curMerge)) $w tag configure merge$diff($top,curMerge) -foreground red showDiff $top $diff($top,curMerge) seeText $w merges$diff($top,curMerge) mergee$diff($top,curMerge) set diff($top,mergeStatus) \ $diff($top,mergeSelection,Comment,$diff($top,curMerge)) } # Select a merge setting for all diffs. proc selectMergeAll {top new} { global diff set end [expr {[llength $diff($top,leftMergeData)] / 2}] for {set t 0} {$t < $end} {incr t} { |
︙ | ︙ | |||
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | set diff($top,mergeSelection,$no) $new set i [expr {$no * 2 + 1}] set diffLeft [lindex $diff($top,leftMergeData) $i] set diffRight [lindex $diff($top,rightMergeData) $i] if {$diff($top,mergeSelection,$no) == 12} { $w insert merges$no $diffLeft$diffRight merge$no } elseif {$diff($top,mergeSelection,$no) == 21} { $w insert merges$no $diffRight$diffLeft merge$no } elseif {$diff($top,mergeSelection,$no) == 1} { $w insert merges$no $diffLeft merge$no } elseif {$diff($top,mergeSelection,$no) == 2} { $w insert merges$no $diffRight merge$no } } # Save the merge result. proc saveMerge {top} { set w $top.merge.t if {$::diff($top,mergeFile) eq "" && $::diff($top,mode) eq "conflict"} { | > > > > > > > > > > > > > > | 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 | set diff($top,mergeSelection,$no) $new set i [expr {$no * 2 + 1}] set diffLeft [lindex $diff($top,leftMergeData) $i] set diffRight [lindex $diff($top,rightMergeData) $i] # Temporarily switch surrounding marks # Two steps are enough since there can't be consecutive empty areas # The one before and/or the one after the one being switch might # be empty. $w mark gravity mergee[expr {$no - 2}] left $w mark gravity mergee[expr {$no - 1}] left $w mark gravity merges[expr {$no + 1}] right $w mark gravity merges[expr {$no + 2}] right if {$diff($top,mergeSelection,$no) == 12} { $w insert merges$no $diffLeft$diffRight merge$no } elseif {$diff($top,mergeSelection,$no) == 21} { $w insert merges$no $diffRight$diffLeft merge$no } elseif {$diff($top,mergeSelection,$no) == 1} { $w insert merges$no $diffLeft merge$no } elseif {$diff($top,mergeSelection,$no) == 2} { $w insert merges$no $diffRight merge$no } # Switch back surrounding marks $w mark gravity mergee[expr {$no - 2}] right $w mark gravity mergee[expr {$no - 1}] right $w mark gravity merges[expr {$no + 1}] left $w mark gravity merges[expr {$no + 2}] left } # Save the merge result. proc saveMerge {top} { set w $top.merge.t if {$::diff($top,mergeFile) eq "" && $::diff($top,mode) eq "conflict"} { |
︙ | ︙ | |||
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | set diff($top,leftMergeData) {} set diff($top,rightMergeData) {} array unset diff $top,mergeSelection,* } # Create a window to display merge result. proc makeMergeWin {top} { if {![info exists ::diff($top,mergetranslation)]} { if {$::tcl_platform(platform) eq "windows"} { set ::diff($top,mergetranslation) crlf } else { set ::diff($top,mergetranslation) lf } } set w $top.merge if {![winfo exists $w]} { toplevel $w } else { destroy {*}[winfo children $w] } | > > | | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | set diff($top,leftMergeData) {} set diff($top,rightMergeData) {} array unset diff $top,mergeSelection,* } # Create a window to display merge result. proc makeMergeWin {top} { collectMergeData $top if {![info exists ::diff($top,mergetranslation)]} { if {$::tcl_platform(platform) eq "windows"} { set ::diff($top,mergetranslation) crlf } else { set ::diff($top,mergetranslation) lf } } set w $top.merge if {![winfo exists $w]} { toplevel $w } else { destroy {*}[winfo children $w] } set anyC $::diff($top,mergeSelection,AnyConflict) wm title $w "Merge result: [TitleTail $top]" menu $w.m $w configure -menu $w.m $w.m add cascade -label "File" -underline 0 -menu $w.m.mf menu $w.m.mf $w.m.mf add command -label "Save" -underline 0 -command "saveMerge $top" $w.m.mf add separator |
︙ | ︙ | |||
316 317 318 319 320 321 322 323 324 325 326 327 328 329 | $w.m.ms add radiobutton -label "Right" -underline 0 -value 2 \ -variable diff($top,curMergeSel) -command "selectMerge $top" $w.m.ms add radiobutton -label "Right+Left" -value 21 \ -variable diff($top,curMergeSel) -command "selectMerge $top" $w.m.ms add separator $w.m.ms add command -label "All Left" -command "selectMergeAll $top 1" $w.m.ms add command -label "All Right" -command "selectMergeAll $top 2" $w.m add cascade -label "Config" -underline 0 -menu $w.m.mc menu $w.m.mc $w.m.mc add radiobutton -label "Line end LF" -value lf -variable diff($top,mergetranslation) $w.m.mc add radiobutton -label "Line end CRLF" -value crlf -variable diff($top,mergetranslation) if {$::diff($top,mode) eq "conflict"} { $w.m.mc add separator | > > > > > > > > > > > > > | 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 | $w.m.ms add radiobutton -label "Right" -underline 0 -value 2 \ -variable diff($top,curMergeSel) -command "selectMerge $top" $w.m.ms add radiobutton -label "Right+Left" -value 21 \ -variable diff($top,curMergeSel) -command "selectMerge $top" $w.m.ms add separator $w.m.ms add command -label "All Left" -command "selectMergeAll $top 1" $w.m.ms add command -label "All Right" -command "selectMergeAll $top 2" $w.m add cascade -label "Goto" -underline 0 -menu $w.m.mg menu $w.m.mg $w.m.mg add command -accelerator "Up" -label "Previous" -command "nextMerge $top -1" $w.m.mg add command -accelerator "Down" -label "Next" -command "nextMerge $top 1" if {$anyC} { $w.m.mg add command -accelerator "Shift-Up" -label "Previous Conflict" -command "nextMerge $top -1000" $w.m.mg add command -accelerator "Shift-Down" -label "Next Conflict" -command "nextMerge $top 1000" } else { $w.m.mg add command -accelerator "Shift-Up" -label "Previous 10" -command "nextMerge $top -10" $w.m.mg add command -accelerator "Shift-Down" -label "Next 10" -command "nextMerge $top 10" } $w.m add cascade -label "Config" -underline 0 -menu $w.m.mc menu $w.m.mc $w.m.mc add radiobutton -label "Line end LF" -value lf -variable diff($top,mergetranslation) $w.m.mc add radiobutton -label "Line end CRLF" -value crlf -variable diff($top,mergetranslation) if {$::diff($top,mode) eq "conflict"} { $w.m.mc add separator |
︙ | ︙ | |||
344 345 346 347 348 349 350 | -command "selectMerge $top" ttk::radiobutton $w.f.rb4 -text "RL" -value 21 \ -variable diff($top,curMergeSel) \ -command "selectMerge $top" bind $w <Key-Left> "focus $w; set diff($top,curMergeSel) 1; selectMerge $top" bind $w <Key-Right> "focus $w; set diff($top,curMergeSel) 2; selectMerge $top" | | | > > > > > > < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 | -command "selectMerge $top" ttk::radiobutton $w.f.rb4 -text "RL" -value 21 \ -variable diff($top,curMergeSel) \ -command "selectMerge $top" bind $w <Key-Left> "focus $w; set diff($top,curMergeSel) 1; selectMerge $top" bind $w <Key-Right> "focus $w; set diff($top,curMergeSel) 2; selectMerge $top" ttk::button $w.f.bl -text "Prev C" -command "nextMerge $top -1000" ttk::button $w.f.br -text "Next C" -command "nextMerge $top 1000" ttk::button $w.f.b1 -text "Prev" -command "nextMerge $top -1" ttk::button $w.f.b2 -text "Next" -command "nextMerge $top 1" bind $w <Key-Down> "focus $w ; nextMerge $top 1" bind $w <Key-Up> "focus $w ; nextMerge $top -1" bind $w <Shift-Key-Down> "focus $w ; nextMerge $top 10" bind $w <Shift-Key-Up> "focus $w ; nextMerge $top -10" ttk::button $w.f.bs -text "Save" -command "saveMerge $top" ttk::button $w.f.bq -text "Close" -command "closeMerge $top" wm protocol $w WM_DELETE_WINDOW "closeMerge $top" grid $w.f.rb1 $w.f.rb2 $w.f.rb3 $w.f.rb4 x $w.f.b1 $w.f.b2 x \ $w.f.bl $w.f.br x $w.f.bs $w.f.bq -sticky we -padx 1 if {!$anyC} { grid forget $w.f.bl $w.f.br } grid columnconfigure $w.f {4 7 10} -minsize 10 grid columnconfigure $w.f 10 -weight 1 grid columnconfigure $w.f {0 1 2 3} -uniform a grid columnconfigure $w.f {5 6 8 9 11 12} -uniform b #grid columnconfigure $w.f {11 13 14} -uniform c text $w.t -width 80 -height 20 -xscrollcommand "$w.sbx set" \ -yscrollcommand "$w.sby set" -font myfont scrollbar $w.sbx -orient horizontal -command "$w.t xview" scrollbar $w.sby -orient vertical -command "$w.t yview" bind $w.t <Key-Escape> [list focus $w] ttk::label $w.ls -textvariable ::diff($top,mergeStatus) # Prevent toplevel bindings on keys to fire while in the text widget. bindtags $w.t [list Text $w.t $w all] bind $w.t <Key-Left> "break" bind $w.t <Key-Right> "break" bind $w.t <Key-Down> "break" bind $w.t <Key-Up> "break" bind $w.t <Shift-Key-Down> "break" bind $w.t <Shift-Key-Up> "break" grid $w.f - -sticky news -row 0 grid $w.t $w.sby -sticky news grid $w.sbx x -sticky we grid $w.ls - -sticky we grid columnconfigure $w 0 -weight 1 grid rowconfigure $w 1 -weight 1 fillMergeWindow $top } # Compare each file against an ancestor file for three-way merge proc collectAncestorInfo {top dFile1 dFile2 opts} { if {![info exists ::diff($top,mergetranslation)]} { # Try to autodetect line endings in ancestor file set ch [open $::diff($top,ancestorFile) rb] set data [read $ch 10000] close $ch if {[string first \r\n $data] >= 0} { set ::diff($top,mergetranslation) crlf } else { set ::diff($top,mergetranslation) lf } } array unset ::diff $top,ancestorLeft,* array unset ::diff $top,ancestorRight,* set differrA1 [catch {DiffUtil::diffFiles {*}$opts \ $::diff($top,ancestorFile) $dFile1} diffresA1] set differrA2 [catch {DiffUtil::diffFiles {*}$opts \ $::diff($top,ancestorFile) $dFile2} diffresA2] if {$differrA1 != 0 || $differrA2 != 0} { puts $diffresA1 puts $diffresA2 return } foreach i $diffresA1 { lassign $i line1 n1 line2 n2 if {$n1 == 0} { # Added lines for {set t $line2} {$t < $line2 + $n2} {incr t} { set ::diff($top,ancestorLeft,$t) a } } elseif {$n2 == 0} { # Deleted lines # Mark the following line set ::diff($top,ancestorLeft,d$line2) d } else { # Changed lines for {set t $line2} {$t < $line2 + $n2} {incr t} { set ::diff($top,ancestorLeft,$t) c } } } foreach i $diffresA2 { lassign $i line1 n1 line2 n2 if {$n1 == 0} { # Added lines for {set t $line2} {$t < $line2 + $n2} {incr t} { set ::diff($top,ancestorRight,$t) a } } elseif {$n2 == 0} { # Deleted lines # Mark the following line set ::diff($top,ancestorRight,d$line2) d } else { # Changed lines for {set t $line2} {$t < $line2 + $n2} {incr t} { set ::diff($top,ancestorRight,$t) c } } } #parray ::diff $top,ancestor* } # Use ancestor info to select which side to use in a merge chunk ##nagelfar syntax WhichSide x x x x x n n proc WhichSide {top line1 n1 line2 n2 conflictName commentName} { upvar 1 $conflictName conflict $commentName comment set conflict 0 set comment "" if {$::diff($top,ancestorFile) eq ""} { # No ancestor info, just select right side return 2 } if {$n1 == 0} { # Only to the right set delLeft [info exists ::diff($top,ancestorLeft,d$line1)] # Inserted to right : Keep right side if {!$delLeft} { set comment "Right: Add" return 2 } for {set t $line2} {$t < $line2 + $n2} {incr t} { if {[info exists ::diff($top,ancestorRight,$t)]} { set right($::diff($top,ancestorRight,$t)) 1 } } # Deleted to left : Keep left side if {[array size right] == 0} { set comment "Left: Delete" return 1 } # Deleted to left and changed to the right : ?? (right for now) # FIXA set comment "*** Left: Delete, Right: Change" set conflict 1 return 2 } elseif {$n2 == 0} { # Only to the left, this can be: set delRight [info exists ::diff($top,ancestorRight,d$line2)] # Inserted to left : Keep left side if {!$delRight} { set comment "Left: Add" return 1 } for {set t $line1} {$t < $line1 + $n1} {incr t} { if {[info exists ::diff($top,ancestorLeft,$t)]} { set left($::diff($top,ancestorLeft,$t)) 1 } } # Deleted to right : Keep right side if {[array size left] == 0} { set comment "Right: Delete" return 2 } # Deleted to right and changed to the left : ?? (right for now) # FIXA set comment "*** Left: Change, Right: Delete" set conflict 1 return 2 } else { # Changed on both sides # Collect left side info for {set t $line1} {$t < $line1 + $n1} {incr t} { if {[info exists ::diff($top,ancestorLeft,$t)]} { set left($::diff($top,ancestorLeft,$t)) 1 } } # No changes against ancestor on left side means it is just # changed to the right : Keep right if {[array size left] == 0} { set comment "Right: Change" return 2 } # Collect right side info for {set t $line2} {$t < $line2 + $n2} {incr t} { if {[info exists ::diff($top,ancestorRight,$t)]} { set right($::diff($top,ancestorRight,$t)) 1 } } # No changes against ancestor on right side means it is just # changed to the left : Keep left if {[array size right] == 0} { set comment "Left: Change" return 1 } if {[info exists left(a)] && ![info exists left(c)] && \ [info exists right(a)] && ![info exists right(c)]} { # Pure add on both sides, keep both set comment "*** Left: Add, Right: Add" set conflict 1 return 12 } # Changed in both, right for now # FIXA set comment "*** Left: Change, Right: Change" set conflict 1 return 2 } } |
Changes to src/plugin.tcl.
︙ | ︙ | |||
20 21 22 23 24 25 26 | # #---------------------------------------------------------------------- # $Revision$ #---------------------------------------------------------------------- proc PluginSearchPath {} { set dirs [list . ./plugins] | | | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # #---------------------------------------------------------------------- # $Revision$ #---------------------------------------------------------------------- proc PluginSearchPath {} { set dirs [list . ./plugins] lappend dirs [file join $::eskil(thisDir) .. ..] lappend dirs [file join $::eskil(thisDir) .. .. plugins] lappend dirs [file join $::eskil(thisDir) .. plugins] return $dirs } # Locate plugin source proc LocatePlugin {plugin} { set src "" set dirs [PluginSearchPath] |
︙ | ︙ | |||
86 87 88 89 90 91 92 | return } set ch [open $src] puts -nonewline [read $ch] close $ch } | | > | | > > > > > > > > > > > > > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | return } set ch [open $src] puts -nonewline [read $ch] close $ch } proc listPlugins {} { set dirs [PluginSearchPath] foreach dir $dirs { set files [glob -nocomplain [file join $dir *.tcl]] foreach file $files { set file [file normalize $file] if {[info exists done($file)]} continue if {![file exists $file]} continue if {![file isfile $file]} continue if {![file readable $file]} continue set done($file) 1 set ch [open $file r] set data [read $ch 200] close $ch if {[regexp {^\#\#Eskil Plugin :(.*?)(\n|$)} $data -> descr]} { set result([file rootname [file tail $file]]) $descr } } } return [array get result] } proc printPlugins {} { set plugins [listPlugins] if {[llength $plugins] == 0} { puts "No plugins found." return } puts "Available plugins:" foreach {plugin descr} $plugins { puts "Plugin \"$plugin\" : $descr" } } proc preparePlugin {top} { #FIXA: plugin miffo disallowEdit $top $::diff($top,plugin) eval [list array set ::Pref [array get ::Pref]] set out1 [tmpFile] |
︙ | ︙ | |||
164 165 166 167 168 169 170 | if {[info exists ::diff($top,rightFileBak)]} { set ::diff($top,rightFile) $::diff($top,rightFileBak) } unset -nocomplain \ ::diff($top,leftFileBak) ::diff($top,rightFileBak) \ ::diff($top,leftFileDiff) ::diff($top,rightFileDiff) } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | if {[info exists ::diff($top,rightFileBak)]} { set ::diff($top,rightFile) $::diff($top,rightFileBak) } unset -nocomplain \ ::diff($top,leftFileBak) ::diff($top,rightFileBak) \ ::diff($top,leftFileDiff) ::diff($top,rightFileDiff) } # GUI for plugin selection proc EditPrefPlugins {top} { set w $top.prefplugin # Create window destroy $w toplevel $w -padx 3 -pady 3 ttk::frame $w._bg place $w._bg -x 0 -y 0 -relwidth 1.0 -relheight 1.0 -border outside wm title $w "Preferences: Plugins" set plugins [listPlugins] if {[llength $plugins] == 0} { grid [ttk::label $w.l -text "No plugins found."] - -padx 3 -pady 3 } if {![info exists ::diff($top,pluginname)]} { set ::diff($top,pluginname) "" } if {![info exists ::diff($top,plugininfo)]} { set ::diff($top,plugininfo) "" } set ::diff($top,edit,pluginname) $::diff($top,pluginname) set ::diff($top,edit,plugininfo) $::diff($top,plugininfo) set t 0 foreach {plugin descr} $plugins { ttk::radiobutton $w.rb$t -variable ::diff($top,edit,pluginname) -value $plugin -text $plugin ttk::label $w.l$t -text $descr -anchor "w" grid $w.rb$t $w.l$t -sticky we -padx 3 -pady 3 incr t } ttk::radiobutton $w.rb$t -variable ::diff($top,edit,pluginname) -value "" -text "No Plugin" grid $w.rb$t -sticky we -padx 3 -pady 3 ttk::label $w.li -text "Info" -anchor "w" ttk::entry $w.ei -textvariable ::diff($top,edit,plugininfo) grid $w.li $w.ei -sticky we -padx 3 -pady 3 ttk::frame $w.fb -padding 3 ttk::button $w.fb.b1 -text "Ok" -command [list EditPrefPluginsOk $top $w] ttk::button $w.fb.b2 -text "Cancel" -command [list destroy $w] set ::widgets($top,prefPluginsOk) $w.fb.b1 grid $w.fb.b1 x $w.fb.b2 -sticky we grid columnconfigure $w.fb {0 2} -uniform a grid columnconfigure $w.fb 1 -weight 1 grid $w.fb - -sticky we grid columnconfigure $w 1 -weight 1 } proc EditPrefPluginsOk {top w} { destroy $w set ::diff($top,pluginname) $::diff($top,edit,pluginname) set ::diff($top,plugininfo) $::diff($top,edit,plugininfo) if {$::diff($top,pluginname) ne ""} { set pinterp [createPluginInterp $::diff($top,pluginname) $::diff($top,plugininfo)] } else { set pinterp "" } set ::diff($top,plugin) $pinterp } |
Changes to src/registry.tcl.
︙ | ︙ | |||
52 53 54 55 56 57 58 | grid $l.new1 $l.new2 - -sticky "w" -padx 4 -pady 4 grid $l.delete - $l.change -sticky "w" -padx 4 -pady 4 grid $l.change -sticky "e" grid columnconfigure $l 2 -weight 1 } proc makeRegistryWin {} { | < < | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | grid $l.new1 $l.new2 - -sticky "w" -padx 4 -pady 4 grid $l.delete - $l.change -sticky "w" -padx 4 -pady 4 grid $l.change -sticky "e" grid columnconfigure $l 2 -weight 1 } proc makeRegistryWin {} { # Locate executable for this program set exe [info nameofexecutable] if {[regexp {^(.*wish)\d+\.exe$} $exe -> pre]} { set alt $pre.exe if {[file exists $alt]} { set a [tk_messageBox -icon question -title "Which Wish" -message \ "Would you prefer to use the executable\n\ |
︙ | ︙ | |||
98 99 100 101 102 103 104 | } else { if {[regexp {wish\d+\.exe} $exe]} { set exe [file join [file dirname $exe] wish.exe] if {[file exists $exe]} { set myexe [list $exe] } } | | | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | } else { if {[regexp {wish\d+\.exe} $exe]} { set exe [file join [file dirname $exe] wish.exe] if {[file exists $exe]} { set myexe [list $exe] } } set myexe [list $exe $::eskil(thisScript)] } set valbase {} foreach item $myexe { lappend valbase \"[file nativename $item]\" } set valbase [join $valbase] |
︙ | ︙ |
Changes to src/rev.tcl.
︙ | ︙ | |||
43 44 45 46 47 48 49 | # eskil::rev::XXX::get {filename outfile rev} # # Get a revision of a file and place it in outfile. # rev is in any format understood by this system, and # should be retrieved from ParseRevs | | > | | | > > | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | # eskil::rev::XXX::get {filename outfile rev} # # Get a revision of a file and place it in outfile. # rev is in any format understood by this system, and # should be retrieved from ParseRevs # eskil::rev::XXX::getPatch {revs {files {}}} # # Get a patch of the file tree, between the revisions given. # revs is in any format understood by this system, and # should be retrieved from ParseRevs # An optional list of files that should be included can be given. # eskil::rev::XXX::commitFile {top args} # # If implemented, enables the commit feature when comparing edited # file(s) agains latest check in. # If no files are given, all edited files are committed. # eskil::rev::XXX::viewLog {top filename revs} # # If implemented, enables the log feature when comparing revisions. # View log between displayed versions namespace eval eskil::rev::CVS {} namespace eval eskil::rev::RCS {} namespace eval eskil::rev::CT {} namespace eval eskil::rev::GIT {} namespace eval eskil::rev::FOSSIL {} namespace eval eskil::rev::SVN {} namespace eval eskil::rev::HG {} namespace eval eskil::rev::BZR {} namespace eval eskil::rev::P4 {} proc eskil::rev::CVS::detect {file} { if {$file eq ""} { |
︙ | ︙ | |||
174 175 176 177 178 179 180 181 182 183 184 185 186 187 | [file isdirectory [file join $dir .. .. .git]]} { if {[auto_execok git] ne ""} { return 1 } } return 0 } proc eskil::rev::P4::detect {file} { if {[auto_execok icmp4] != ""} { if {[catch {exec csh -c "icmp4 have $file"} p4have]} { return 0 } if {[lindex $p4have 1] eq "-"} { return 1 } } return 0 | > > > > > > > > > > > > > > > > > > | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | [file isdirectory [file join $dir .. .. .git]]} { if {[auto_execok git] ne ""} { return 1 } } return 0 } proc eskil::rev::FOSSIL::detect {file} { if {$file eq ""} { set dir [pwd] } else { set dir [file dirname $file] } # Fossil, detect three steps down. Could be improved. FIXA if {[file exists [file join $dir _FOSSIL_]] || [file exists [file join $dir .. _FOSSIL_]] || [file exists [file join $dir .. .. _FOSSIL_]] || [file exists [file join $dir .. .. .. _FOSSIL_]]} { if {[auto_execok fossil] ne ""} { return 1 } } return 0 } proc eskil::rev::P4::detect {file} { if {[auto_execok icmp4] != ""} { if {[catch {exec csh -c "icmp4 have $file"} p4have]} { return 0 } if {[lindex $p4have 1] eq "-"} { return 1 } } return 0 |
︙ | ︙ | |||
211 212 213 214 215 216 217 | if {$old != ""} { cd $old } } # Get a CVS patch | | > | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | if {$old != ""} { cd $old } } # Get a CVS patch proc eskil::rev::CVS::getPatch {revs {files {}}} { if {$::Pref(context) > 0} { set context $::Pref(context) } else { set context 5 } # TODO: support files set cmd [list exec cvs diff -U $context] foreach rev $revs { lappend cmd -r $rev } if {[catch {eval $cmd} res]} { if {![string match "*=========*" $res]} { |
︙ | ︙ | |||
259 260 261 262 263 264 265 | if {$old != ""} { cd $old } } # Get a SVN patch | | > | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | if {$old != ""} { cd $old } } # Get a SVN patch proc eskil::rev::SVN::getPatch {revs {files {}}} { set cmd [list exec svn diff] foreach rev $revs { lappend cmd -r $rev } lappend cmd {*}$files if {[catch {eval $cmd} res]} { tk_messageBox -icon error -title "SVN error" -message $res return "" } return $res } |
︙ | ︙ | |||
300 301 302 303 304 305 306 | if {$old != ""} { cd $old } } # Get a HG patch | | > | 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | if {$old != ""} { cd $old } } # Get a HG patch proc eskil::rev::HG::getPatch {revs {files {}}} { # TODO: support files set cmd [list exec hg diff] foreach rev $revs { lappend cmd -r $rev } if {[catch {eval $cmd} res]} { tk_messageBox -icon error -title "HG error" -message $res |
︙ | ︙ | |||
341 342 343 344 345 346 347 | if {$old != ""} { cd $old } } # Get a BZR patch | | > | 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | if {$old != ""} { cd $old } } # Get a BZR patch proc eskil::rev::BZR::getPatch {revs {files {}}} { # TODO: support files set cmd [list exec bzr diff] if {[llength $revs] == 2} { lappend cmd -r [lindex $revs 0]..[lindex $revs 1] } elseif {[llength $revs] == 1} { lappend cmd -r [lindex $revs 0] } |
︙ | ︙ | |||
365 366 367 368 369 370 371 | # Get an RCS revision proc eskil::rev::RCS::get {filename outfile {rev {}}} { catch {exec co -p$rev [file nativename $filename] \ > $outfile} } # Get a RCS patch | | > > > | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 | # Get an RCS revision proc eskil::rev::RCS::get {filename outfile {rev {}}} { catch {exec co -p$rev [file nativename $filename] \ > $outfile} } # Get a RCS patch proc eskil::rev::RCS::getPatch {revs {files {}}} { # Not supported yet. return "" } # Get a GIT revision # No support for revisions yet proc eskil::rev::GIT::get {filename outfile rev} { set old [pwd] set dir [file dirname $filename] set tail [file tail $filename] # Locate the top directory while {![file isdirectory $dir/.git]} { set thisdir [file tail $dir] set dir [file dirname $dir] set tail [file join $thisdir $tail] } if {$rev eq ""} { set rev HEAD } cd $dir catch {exec git show $rev:$tail > $outfile} cd $old # example: git show HEAD^^^:apa } |
︙ | ︙ | |||
405 406 407 408 409 410 411 | } cd $dir catch {exec git add $tail} cd $old } # Get a GIT patch | | | > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 | } cd $dir catch {exec git add $tail} cd $old } # Get a GIT patch proc eskil::rev::GIT::getPatch {revs {files {}}} { set cmd [list exec git diff -p] if {[llength $revs] == 0} { # Always default to HEAD to see changes regardless of index lappend cmd HEAD } else { foreach rev $revs { lappend cmd $rev } } lappend cmd "--" {*}$files if {[catch {eval $cmd} res]} { tk_messageBox -icon error -title "GIT error" -message $res return "" } return $res } # Get a FOSSIL revision # No support for revisions yet proc eskil::rev::FOSSIL::get {filename outfile rev} { set old [pwd] set dir [file dirname $filename] set tail [file tail $filename] # Locate the top directory while {![file exists $dir/_FOSSIL_]} { set thisdir [file tail $dir] set dir [file dirname $dir] set tail [file join $thisdir $tail] } cd $dir if {$rev eq "HEAD" || $rev eq ""} { catch {exec fossil finfo -p $tail > $outfile} } else { catch {exec fossil finfo -p $tail -r $rev > $outfile} } cd $old } # Get a FOSSIL patch proc eskil::rev::FOSSIL::getPatch {revs {files {}}} { set cmd [list exec fossil diff] if {[llength $revs] >= 1} { lappend cmd --from [lindex $revs 0] } if {[llength $revs] >= 2} { lappend cmd --to [lindex $revs 1] } if {[llength $files] > 0} { # Fossil diff only handles one file at a time. set res "" foreach file $files { set fcmd $cmd lappend fcmd $file if {[catch {eval $cmd} fres]} { tk_messageBox -icon error -title "FOSSIL error" -message $fres return "" } append res $fres } } else { if {[catch {eval $cmd} res]} { tk_messageBox -icon error -title "FOSSIL error" -message $res return "" } } return $res } # Get a ClearCase revision proc eskil::rev::CT::get {filename outfile rev} { set filerev [file nativename $filename@@$rev] if {[catch {exec cleartool get -to $outfile $filerev} msg]} { tk_messageBox -icon error -title "Cleartool error" -message $msg return } } # Get a CT patch proc eskil::rev::CT::getPatch {revs {files {}}} { # Not supported yet return "" } # Get a P4 revision proc eskil::rev::P4::get {filename outfile rev} { set dir [file dirname $filename] |
︙ | ︙ | |||
537 538 539 540 541 542 543 | foreach rev $revs { switch -glob -- $rev { HEAD - master - * { # Let anything through for now lappend result $rev } } } | | > > > > | > > > > > > | 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 | foreach rev $revs { switch -glob -- $rev { HEAD - master - * { # Let anything through for now lappend result $rev } } } return $result } # Figure out FOSSIL revision from arguments proc eskil::rev::FOSSIL::ParseRevs {filename revs} { set result "" foreach rev $revs { switch -glob -- $rev { HEAD - master - * { # Let anything through for now FIXA lappend result $rev } } } return $result } # Figure out HG revision from arguments proc eskil::rev::HG::ParseRevs {filename revs} { set result "" |
︙ | ︙ | |||
687 688 689 690 691 692 693 | if {$revs == ""} { set revs -1 } foreach rev $revs { if {[string is digit $rev]} { lappend result $rev } else { if {[catch {exec csh -c "icmp4 files $filename"} res]} { tk_messageBox -icon error \ | | | > > > > > > > | | | > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 | if {$revs == ""} { set revs -1 } foreach rev $revs { if {[string is digit $rev]} { lappend result $rev } else { if {[catch {exec csh -c "icmp4 files $filename"} res]} { tk_messageBox -icon error \ -message "Failed p4 files filename: $rev" exit } regexp {\#(\d+)} [file tail $res] -> res if {$rev != ""} { incr res $rev } lappend result $res } } return $result } # Check in CVS controlled file proc eskil::rev::CVS::commitFile {top args} { if {[llength $args] == 0} { set target all } elseif {[llength $args] == 1} { set target [file tail [lindex $args 0]] } else { set target "[file tail [lindex $args 0]] ..." } set logmsg [LogDialog $top $target] if {$logmsg ne ""} { catch {exec cvs -q commit -m $logmsg {*}$args} } } # Check in SVN controlled file proc eskil::rev::SVN::commitFile {top args} { if {[llength $args] == 0} { set target all } elseif {[llength $args] == 1} { set target [file tail [lindex $args 0]] } else { set target "[file tail [lindex $args 0]] ..." } set logmsg [LogDialog $top $target] if {$logmsg ne ""} { catch {exec svn -q commit -m $logmsg {*}$args} } } # Check in GIT controlled file proc eskil::rev::GIT::commitFile {top args} { if {[llength $args] == 0} { set target all } elseif {[llength $args] == 1} { set target [file tail [lindex $args 0]] } else { set target "[file tail [lindex $args 0]] ..." } set logmsg [LogDialog $top $target] if {$logmsg eq ""} return if {[llength $args] == 0} { catch {exec git commit -a -m $logmsg} } else { catch {exec git commit -m $logmsg {*}$args} } } # Check in Fossil controlled file proc eskil::rev::FOSSIL::commitFile {top args} { if {[llength $args] == 0} { set target all } elseif {[llength $args] == 1} { set target [file tail [lindex $args 0]] } else { set target "[file tail [lindex $args 0]] ..." } set logmsg [LogDialog $top $target] if {$logmsg eq ""} return catch {exec fossil commit -m $logmsg {*}$args} } # View log between displayed versions proc eskil::rev::CVS::viewLog {top filename revs} { set cmd [list exec cvs -q log -N] if {[llength $revs] > 1} { lappend cmd -r[join $revs ":"] } else { |
︙ | ︙ | |||
776 777 778 779 780 781 782 | if {![file exists $file]} { return "" } if {[info exists cache($file)]} { return $cache($file) } } | | | 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 | if {![file exists $file]} { return "" } if {[info exists cache($file)]} { return $cache($file) } } set searchlist [list $preference GIT FOSSIL HG BZR P4] foreach ns [namespace children eskil::rev] { lappend searchlist [namespace tail $ns] } foreach rev $searchlist { set result [eskil::rev::${rev}::detect $file] if {$result} { set cache($file) $rev |
︙ | ︙ | |||
805 806 807 808 809 810 811 | set ::diff($top,rightFile) $file set ::diff($top,rightOK) 1 set ::diff($top,leftLabel) $rev set ::diff($top,leftOK) 0 set ::Pref(toolbar) 1 } | | | 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 | set ::diff($top,rightFile) $file set ::diff($top,rightOK) 1 set ::diff($top,leftLabel) $rev set ::diff($top,leftOK) 0 set ::Pref(toolbar) 1 } # Prepare for revision diff. Checkout copies of the versions needed. proc prepareRev {top} { global Pref $::widgets($top,commit) configure -state disabled $::widgets($top,log) configure -state disabled set type $::diff($top,modetype) |
︙ | ︙ | |||
876 877 878 879 880 881 882 | $::widgets($top,log) configure -state normal } } # Make sure labels are updated before processing starts update idletasks } | | > > > > > | > > > > > > > > > > | | | | 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 | $::widgets($top,log) configure -state normal } } # Make sure labels are updated before processing starts update idletasks } # Clean up after a revision diff. proc cleanupRev {top} { global Pref clearTmp $::diff($top,rightFile) $::diff($top,leftFile) set ::diff($top,rightFile) $::diff($top,RevFile) set ::diff($top,leftFile) $::diff($top,RevFile) } proc revCommit {top} { if {[$::widgets($top,commit) cget -state] eq "disabled"} return set type $::diff($top,modetype) if {$::diff($top,mode) eq "patch"} { set files $::diff($top,reviewFiles) } else { set files [list $::diff($top,RevFile)] } eskil::rev::${type}::commitFile $top {*}$files } proc revLog {top} { if {[$::widgets($top,log) cget -state] eq "disabled"} return set type $::diff($top,modetype) eskil::rev::${type}::viewLog $top $::diff($top,RevFile) \ $::diff($top,RevRevs) } # Get a complete tree patch from this system. proc getFullPatch {top} { global Pref $::widgets($top,commit) configure -state disabled $::widgets($top,log) configure -state disabled set type $::diff($top,modetype) set files $::diff($top,reviewFiles) set revs {} # Search for revision options if {$::diff($top,doptrev1) != ""} { lappend revs $::diff($top,doptrev1) } if {$::diff($top,doptrev2) != ""} { lappend revs $::diff($top,doptrev2) } set revs [eskil::rev::${type}::ParseRevs "" $revs] set revlabels {} foreach rev $revs { lappend revlabels [GetLastTwoPath $rev] } if {[llength $revs] == 0} { if {[info commands eskil::rev::${type}::commitFile] ne ""} { $::widgets($top,commit) configure -state normal } } return [eskil::rev::${type}::getPatch $revs $files] } ############################################################################## # Utilities ############################################################################## # Get the last two elements in a file path proc GetLastTwoPath {path} { set last [file tail $path] set penultimate [file tail [file dirname $path]] if {$penultimate eq "."} { return $last } else { return [file join $penultimate $last] } } # Dialog for log message proc LogDialog {top target {clean 0}} { set w $top.logmsg destroy $w toplevel $w -padx 3 -pady 3 wm title $w "Commit log message for $target" set ::diff($top,logdialogok) 0 text $w.t -width 70 -height 10 if {!$clean && [info exists ::diff(logdialog)]} { $w.t insert end $::diff(logdialog) $w.t tag add sel 1.0 end-1c |
︙ | ︙ |
Added tests/ancestor.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | 0 1 Added left 2 3 4 Added right 5 6 7 Changed same 8 9 10 Changed different 12 13 14 Deleted left 16 17 18 Deleted right 19 20 21 Left: Add+change Right: change 22 23 24 Left: change Right add+change 25 26 27 Left: Delete Right: change 28 29 30 Left: change Right: delete 31 32 33 Added same 34 35 36 Deleted same 37 38 39 Changed adjacent 40 41 42 Left: Add+change Right: change same 43 44 45 Left: change same Right: add+change 46 47 48 Left: change Right: deleted block 49 50 51 52 Added different 53 54 55 Left mixed change 56 57 58 59 60 Right mixed change 61 62 63 64 65 Both added multiple 66 67 |
Added tests/gui.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | #------------------------------------------------------------*- tcl -*- # Tests for GUI #---------------------------------------------------------------------- # $Revision$ #---------------------------------------------------------------------- lappend ::auto_path /home/peter/src/TkTest package require TkTest wm withdraw . proc XauthSecure {} { global tcl_platform if {[string compare unix $tcl_platform(platform)]} { # This makes no sense outside of Unix return } set hosts [exec xhost] # the first line is info only foreach host [lrange [split $hosts \n] 1 end] { exec xhost -$host } exec xhost - } XauthSecure proc RestartClient {args} { set ::clientfile ./eskil.kit #if {[file exists ${::clientfile}_i]} { # set ::clientfile ${::clientfile}_i #} if {![catch {send -async Eskil exit}]} { update after 500 } set slavepid [exec $::clientfile -server {*}$args &] after 1000 while {[catch {tktest::init Eskil}]} { after 500 } tktest::cmd wm geometry . +10+10 #set files [tktest::widget -class Listbox -pos 1 -eval "get 0 end"] #if {($mode == 0 && $files ne "_testfile_") || \ # ($mode != 0 && $files ne "")} { # exec kill $slavepid # puts "Another nagelfar is running. Can't do GUI tests." # exit #} } proc DeleteFileToTest {file} { set w [tktest::widget -class Listbox -pos 1] set cont [tktest::cmd $w get 0 end] set i [lsearch $cont $file] if {$i < 0} return tktest::cmd $w see $i set coord [tktest::coord $w bbox $i] tktest::mouse left $coord tktest::key Delete } proc AddFileToTest {file {dialog 0}} { # Dialog = 1 : use gui # Dialog = 2 ; use gui+cancel if {$dialog != 0} { tktest::waitFocus press Add 1 if {$dialog != 1} { tktest::press Cancel } else { set e [tktest::widget -class Entry] tktest::cmd $e insert end $file tktest::press Open } } if {$dialog != 1} { tktest::cmd fileDropFile $file } } proc ResetFilters {} { # FIXA: there should be a GUI way of doing this. tktest::cmd set ::Nagelfar(filter) {} } # Get all lines from the text widget, as a list proc GetTextLines {} { set str [tktest::widget -class Text -eval "get 1.0 end"] return [split [string trim $str] \n] } test gui-1.1 {Run 3-way merge} -setup { set f1 [tcltest::makeFile {} _test1] } -body { RestartClient -fine -a tests/ancestor.txt tests/left.txt tests/right.txt -o $f1 tktest::waitFocus press Save tktest::waitFocus press No tktest::press Close catch {exec diff $f1 tests/merge.txt} } -cleanup { tcltest::removeFile {} _test1 } -result {0} catch {tktest::menu File Quit} catch {send -async Eskil exit} update |
Added tests/left.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 0 1 Added left x 2 3 4 Added right 5 6 7 Changed same 8a 9 10 Changed different 12a 13 14 Deleted left 17 18 Deleted right 19 20 21 Left: Add+change Right: change xx 22a 23 24 Left: change Right add+change 25a 26 27 Left: Delete Right: change 29 30 Left: change Right: delete 31a 32 33 Added same xxx 34 35 36 Deleted same 38 39 Changed adjacent 40a 41 42 Left: Add+change Right: change same xxxx 43a 44 45 Left: change same Right: add+change 46a 47 48 Left: change Right: deleted block 49 50a 51 52 Added different xxxxx 53 54 55 Left mixed change 57x 59 60 Right mixed change 61 62 63 64 65 Both added multiple xx1 xx2 66 67 |
Added tests/merge.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | 0 1 Added left x 2 3 4 Added right y 5 6 7 Changed same 8a 9 10 Changed different 12b 13 14 Deleted left 17 18 Deleted right 20 21 Left: Add+change Right: change xx 22b 23 24 Left: change Right add+change yy 25b 26 27 Left: Delete Right: change 28a 29 30 Left: change Right: delete 32 33 Added same xxx 34 35 36 Deleted same 38 39 Changed adjacent 40a 41a 42 Left: Add+change Right: change same xxxx 43a 44 45 Left: change same Right: add+change yyyy 46a 47 48 Left: change Right: deleted block 52 Added different xxxxx yyyyy 53 54 55 Left mixed change 57x 59 60 Right mixed change 61x 63x 64 65 Both added multiple xx1 xx2 yy1 yy2 66 67 |
Changes to tests/patch.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # Tests for patch file parsingunctions -*- tcl -*- #---------------------------------------------------------------------- # $Revision$ #---------------------------------------------------------------------- # Overload exec during these tests set ::diff(gurka,patchFile) "" stub update args {} stub getFullPatch {top} { return $::testpatch } stub displayOnePatch {top leftLines rightLines leftLine rightLine} { } stub emptyLine {top n {highlight 1}} { | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # Tests for patch file parsingunctions -*- tcl -*- #---------------------------------------------------------------------- # $Revision$ #---------------------------------------------------------------------- # Overload exec during these tests set ::diff(gurka,patchFile) "" set ::diff(gurka,patchData) "" stub update args {} stub getFullPatch {top} { return $::testpatch } stub displayOnePatch {top leftLines rightLines leftLine rightLine} { } stub emptyLine {top n {highlight 1}} { |
︙ | ︙ |
Changes to tests/rev.test.
︙ | ︙ | |||
277 278 279 280 281 282 283 284 285 286 287 288 289 290 | file delete .bzr } set res } -cleanup { tcltest::removeFile {} _rev2_11 } -result {BZR} test rev-3.1 { Subversion revisions } -body { eskil::rev::SVN::ParseRevs filename -1 } -result {157} test rev-3.2 { | > > > > > > > > > > > > > > > > > > | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | file delete .bzr } set res } -cleanup { tcltest::removeFile {} _rev2_11 } -result {BZR} test rev-2.12 { Detecting, Fossil } -body { set f [tcltest::makeFile {} _rev2_12] set ::auto_execs(fossil) "x" set apa [file exists _FOSSIL_] if {!$apa} { file mkdir _FOSSIL_ } set res [detectRevSystem $f] if {!$apa} { file delete _FOSSIL_ } set res } -cleanup { tcltest::removeFile {} _rev2_12 } -result {FOSSIL} test rev-3.1 { Subversion revisions } -body { eskil::rev::SVN::ParseRevs filename -1 } -result {157} test rev-3.2 { |
︙ | ︙ |
Added tests/right.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | 0 1 Added left 2 3 4 Added right y 5 6 7 Changed same 8a 9 10 Changed different 12b 13 14 Deleted left 16 17 18 Deleted right 20 21 Left: Add+change Right: change 22b 23 24 Left: change Right add+change yy 25b 26 27 Left: Delete Right: change 28a 29 30 Left: change Right: delete 32 33 Added same xxx 34 35 36 Deleted same 38 39 Changed adjacent 40 41a 42 Left: Add+change Right: change same 43a 44 45 Left: change same Right: add+change yyyy 46a 47 48 Left: change Right: deleted block 52 Added different yyyyy 53 54 55 Left mixed change 56 57 58 59 60 Right mixed change 61x 63x 64 65 Both added multiple yy1 yy2 66 67 |