Eskil

Check-in [d432ba22e3]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Rebuilt command line option handling
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d432ba22e389dc7cd6a21d31f68ef336b9d97d47
User & Date: peter 2015-11-21 02:52:14.293
Context
2015-11-22
19:09
Put Pref option handling into new option handling framework check-in: 69209dc355 user: peter tags: trunk
2015-11-21
02:52
Rebuilt command line option handling check-in: d432ba22e3 user: peter tags: trunk
02:13
Adapted test to compressed pdf check-in: b86ab111b4 user: peter tags: trunk
Changes
Side-by-Side Diff Ignore Whitespace Patch
Changes to Changes.



1
2
3
4
5
6
7
1
2
3
4
5
6
7
8
9
10
+
+
+







2015-11-20
 Rebuilt command line option handling.

2015-11-19
 Added binary plugin.

2015-11-17
 Compress printed PDF.

2015-10-14
Changes to src/eskil.tcl.
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47







-
+







# 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.7+ 2015-11-17"
set ::eskil(diffver) "Version 2.7+ 2015-11-20"
set ::eskil(thisScript) [file join [pwd] [info script]]

namespace import tcl::mathop::+
namespace import tcl::mathop::-
namespace import tcl::mathop::*
namespace import tcl::mathop::/

92
93
94
95
96
97
98
99
100


101
102
103
104
105
106
107
92
93
94
95
96
97
98


99
100
101
102
103
104
105
106
107







-
-
+
+







        set ext [file extension $fontfile]
        if {$ext eq ".afm"} {
            pdf4tcl::loadBaseType1Font EskilBase $fontfile \
                    [file rootname $fontfile].pfb
        } else {
            pdf4tcl::loadBaseTrueTypeFont EskilBase $fontfile 1
        }
        
        pdf4tcl::createFont EskilBase EskilFont cp1251 

        pdf4tcl::createFont EskilBase EskilFont cp1251
        set ::eskil(printFont) EskilFont
    }

    # Figure out a place to store temporary files.
    locateTmp ::eskil(tmpdir)

    if {$::tcl_platform(platform) eq "windows"} {
364
365
366
367
368
369
370
371

372
373
374
375

376
377
378
379
380
381
382
364
365
366
367
368
369
370

371
372
373
374

375
376
377
378
379
380
381
382







-
+



-
+







        set words [split $text $RE]
        set id [$::widgets($top,wTable) insert end $words]
        if {$tag ne "equal"} {
            set col 0
            foreach w $words {
                if {$n == 1} {
                    # TBD TABLE, r is faked here for now
                    dict set ::eskil($top,tablechanges) $id,$col w1 $w 
                    dict set ::eskil($top,tablechanges) $id,$col w1 $w
                    dict set ::eskil($top,tablechanges) $id,$col w2 ""
                    dict set ::eskil($top,tablechanges) $id,$col r  "0 0 1 1"
                } else {
                    dict set ::eskil($top,tablechanges) $id,$col w1 "" 
                    dict set ::eskil($top,tablechanges) $id,$col w1 ""
                    dict set ::eskil($top,tablechanges) $id,$col w2 $w
                    dict set ::eskil($top,tablechanges) $id,$col r  "0 0 1 1"
                }
                incr col
            }
        }
        return
539
540
541
542
543
544
545
546

547
548
549
550
551
552
553
539
540
541
542
543
544
545

546
547
548
549
550
551
552
553







-
+








        # Lap 2, collect cell changes once we have the row id
        set col -1
        foreach w1 $words1 w2 $words2 r $rs {
            incr col
            # Equal? Skip
            if {[llength $r] <= 2} continue
            dict set ::eskil($top,tablechanges) $id,$col "w1" $w1 
            dict set ::eskil($top,tablechanges) $id,$col "w1" $w1
            dict set ::eskil($top,tablechanges) $id,$col "w2" $w2
            dict set ::eskil($top,tablechanges) $id,$col "r"  $r
        }

        incr doingLine1
        incr doingLine2
        return
1706
1707
1708
1709
1710
1711
1712
1713

1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731

1732
1733
1734
1735
1736
1737
1738
1706
1707
1708
1709
1710
1711
1712

1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730

1731
1732
1733
1734
1735
1736
1737
1738







-
+

















-
+








    if {$::eskil($top,view) eq "table"} {
        # Look for table header line
        set i [lindex $diffres 0]
        lassign $i line1 n1 line2 n2
        if {$line1 == 1 || $line2 == 1} {
            # Hide header line of widget TBD TABLE
            #$::widgets($top,wTable) configure 
            #$::widgets($top,wTable) configure
            # Set up columns??
            $::widgets($top,wTable) configure \
                    -columns "0 Table 0 without 0 header 0 not 0 implemented 0 yet"
        } else {
            # First lines are equal, treat them as header
            # Consume table header line
            gets $ch1 line1
            incr doingLine1
            gets $ch2 line
            incr doingLine2
            if {$::eskil($top,separator) eq ""} {
                # Autodetect separator
                # Any tab?
                if {[regsub -all "\t" $line1 "\t" _] >= 2} {
                    set ::eskil($top,separator) "\t"
                } elseif {[regsub -all "," $line1 "," _] >= 2} {
                    set ::eskil($top,separator) ","
                } 
                }
            }
            set headings [split $line1 $::eskil($top,separator)]
            set columns {}
            foreach heading $headings {
                lappend columns 0 $heading
            }
            $::widgets($top,wTable) configure -columns $columns
3450
3451
3452
3453
3454
3455
3456
3457

3458
3459
3460
3461
3462
3463
3464
3450
3451
3452
3453
3454
3455
3456

3457
3458
3459
3460
3461
3462
3463
3464







-
+







        $body tag configure new2 -foreground $::Pref(colornew2) \
                -background $::Pref(bgnew2)
        $body tag configure change -foreground $::Pref(colorchange) \
                -background $::Pref(bgchange)

        set bg [ttk::style configure . -background]
        set map [createMap $top $bg]
        

        grid $top.ft.tab $top.ft.vsb $map -sticky news
        grid $top.ft.hsb x           x    -sticky news
        grid columnconfigure $top.ft 0 -weight 1
        grid rowconfigure    $top.ft 0 -weight 1
        grid $map -pady [expr {[winfo reqwidth $top.ft.vsb] - 2}]
        set ::widgets($top,wTable) $top.ft.tab
    } else {
4175
4176
4177
4178
4179
4180
4181































































4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199

4200
4201
4202
4203
4204
4205
4206






























4207
4208
4209
4210
4211










4212
4213
4214
4215

4216
4217
4218
4219
4220
4221
4222
4223
4224
4225

4226
4227
4228
4229

4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244




4245
4246
4247
4248
4249
4250
4251

4252
4253
4254
4255
4256

4257
4258
4259
4260
4261

4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297

4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315

4316
4317

4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331


4332
4333
4334


4335

4336
4337

4338
4339
4340




4341
4342







4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358







































4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376


































4377
4378

4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402


















































4403
4404
4405




4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417





























4418
4419
4420
4421
4422
4423
4424
4425
4426
4427






















4428
4429


4430
4431
4432
4433
4434
4435

















4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447














4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477


4478

4479
4480
4481
4482
4483
4484
4485
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263







4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293





4294
4295
4296
4297
4298
4299
4300
4301
4302
4303

4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316

4317




4318















4319
4320
4321
4322







4323





4324





4325




































4326


















4327


4328








4329
4330
4331
4332


4333
4334

4335
4336
4337
4338

4339


4340

4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
















4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394


















4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428


4429
























4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479



4480
4481
4482
4483












4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512










4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534


4535
4536






4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553












4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567






























4568
4569

4570
4571
4572
4573
4574
4575
4576
4577







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


















+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-



+









-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-




-
-
+
+
-


+
+
-
+
-
-
+
-


+
+
+
+


+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+







        }
    }
    if {$fail} {
        puts "Argument $opt must be a list of RBG values from 0.0 to 1.0"
        exit
    }
}

# Option/flag handling helpers
proc initOpts {} {
    set ::eskil(opts) {}
}
# Add a command line flag that do not take a value
proc addFlags {args} {
    foreach name $args {
        dict set ::eskil(opts) $name 0
        dict set ::eskil(opts,info) $name flag  1
        dict set ::eskil(opts,info) $name given 0
        dict set ::eskil(opts,info) $name multi 0
    }
}
# Add a command line option that takes a value
proc addOpt {name {def ""}} {
    dict set ::eskil(opts) $name $def
    dict set ::eskil(opts,info) $name flag  0
    dict set ::eskil(opts,info) $name given 0
    dict set ::eskil(opts,info) $name multi 0
}
# Add a command line option that takes multiple values
proc addMultOpt {name} {
    dict set ::eskil(opts) $name {}
    dict set ::eskil(opts,info) $name flag  0
    dict set ::eskil(opts,info) $name given 0
    dict set ::eskil(opts,info) $name multi 1
}
# List all known options
proc allOpts {{pat *}} {
    return [dict keys $::eskil(opts) $pat]
}
proc optIsFlag {arg} {
    return [dict get $::eskil(opts,info) $arg flag]
}
proc optIsGiven {arg valName} {
    upvar 1 $valName val
    set val [dict get $::eskil(opts) $arg]
    return [dict get $::eskil(opts,info) $arg given]
}
proc optSet {arg val} {
    if {[dict get $::eskil(opts,info) $arg multi]} {
        dict lappend ::eskil(opts) $arg $val
    } else {
        dict set ::eskil(opts) $arg $val
    }
    dict set ::eskil(opts,info) $arg given 1
}
proc optGet {arg} {
    return [dict get $::eskil(opts) $arg]
}

# Helper to add a file argument to list of files
proc cmdLineAddFile {filesName arg} {
    upvar 1 $filesName files
    set apa [file normalize [file join [pwd] $arg]]
    if {![file exists $apa]} {
        puts "Bad argument: $arg"
        exit
    } else {
        lappend files $apa
    }
}

# 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

    set ::eskil(autoclose) 0
    set ::eskil(ignorenewline) 0
    set ::eskil(defaultopts) {}

    if {$::eskil(argc) == 0} {
        Init
        return [makeDiffWin]
    }

    # Set up all options info
    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 -noempty -pivot
        -printHeaderSize -printCharsPerLine -printPaper
        -printColorChange -printColorOld -printColorNew
        -printFont -sep
    initOpts
    addFlags -w -b -noignore
    addFlags -i -nocase -nodigit -nokeyword
    addFlags --help -help
    addFlags -noparse -line -smallblock -block
    addFlags -char -word
    addFlags -dir -clip -patch -conflict -review -table
    addFlags -browse -noempty -nodiff
    addFlags -server -fine -cvs -svn -debug
    addFlags -foreach -close
    addFlags -nonewline -nonewline+ -nocdiff
    addFlags -pluginlist -pluginallow
    # Options that take values
    addOpt   -plugin
    addOpt   -plugininfo
    addOpt   -plugindump
    # These options affect Pref
    addOpt   -pivot
    addOpt   -context
    addMultOpt -prefix
    addMultOpt -preprocess
    addMultOpt -preprocessleft
    addMultOpt -preprocessright
    addOpt   -printHeaderSize
    addOpt   -printCharsPerLine
    addOpt   -printPaper
    addOpt   -printColorChange
    addOpt   -printColorOld
    addOpt   -printColorNew
    addOpt   -printFont
        -server -o -a -fine -r -context -cvs -svn -review
        -foreach -preprocess -preprocessleft -preprocessright
        -close -nonewline -plugin -plugininfo -pluginallow
        -plugindump -pluginlist -nocdiff -table -maxwidth
    }
    # These affect opts
    addOpt   -limit
    addOpt   -maxwidth
    addOpt   -o
    addOpt   -a
    addOpt   -sep
    addOpt   -print
    addOpt   -printpdf ;# Old option
    addMultOpt -r


    # 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]
        set allOpts [allOpts]
        if {[lsearch -exact $allOpts $arg] < 0} {
            set match [lsearch -glob -all -inline $allOpts $arg*]
        } else {
            set match [list $arg]
        }
        puts [lsort -dictionary $match]
        exit
    }

    set noautodiff 0
    # Go through and fill in options
    set autobrowse 0
    set dodir 0
    set doclip 0
    set files ""
    set files {}
    set nextArg ""
    set revNo 1
    set dopatch 0
    set doreview 0
    set foreach 0
    set preferedRev "GIT"
    set plugin ""
    set plugininfo ""
    set plugindump ""
    set pluginlist 0
    set pluginallow 0
    set nocdiff 0

    foreach arg $::eskil(argv) {
        if {$nextArg != ""} {
    for {set i 0} {$i < [llength $::eskil(argv)]} {incr i} {
        set arg [lindex $::eskil(argv) $i]
        # Non-dash means not an option
        if {[string index $arg 0] ne "-"} {
            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 "separator"} {
                # Handle if separator is given e.g. as '\t'
                set opts(separator) [subst -nocommands -novariables $arg]
            cmdLineAddFile files $arg
            } elseif {$nextArg eq "printFile"} {
                set opts(printFile) [file join [pwd] $arg]
                set opts(printFileCmd) 1
            } elseif {$nextArg eq "printFont"} {
                set ::Pref(printFont) $arg
            continue
            } elseif {$nextArg eq "printHeaderSize"} {
                if {![string is double -strict $arg] || $arg <= 0} {
                    puts "Argument -printHeaderSize must be a positive number"
                    exit
                }
        }
                set ::Pref(printHeaderSize) $arg
            } elseif {$nextArg eq "printCharsPerLine"} {
                if {![string is integer -strict $arg] || $arg <= 0} {
                    puts "Argument -printCharsPerLine must be a positive number"
                    exit
                }
                set ::Pref(printCharsPerLine) $arg
            } elseif {$nextArg eq "printPaper"} {
                package require pdf4tcl
                if {[llength [pdf4tcl::getPaperSize $arg]] != 2} {
                    puts "Argument -printPaper must be a valid paper size"
                    puts "Valid paper sizes:"
                    puts [join [lsort -dictionary [pdf4tcl::getPaperSizeList]] \n]
                    exit
                }
                set ::Pref(printPaper) $arg
            } elseif {$nextArg eq "printColorChange"} {
                ValidatePdfColor $arg -printColorChange
                set ::Pref(printColorChange) $arg
            } elseif {$nextArg eq "printColorOld"} {
                ValidatePdfColor $arg -printColorOld
                set ::Pref(printColorNew1) $arg
            } elseif {$nextArg eq "printColorNew"} {
                ValidatePdfColor $arg -printColorNew
                set ::Pref(printColorNew2) $arg
            } elseif {$nextArg eq "revision"} {
                set opts(doptrev$revNo) $arg
                incr revNo
            } elseif {$nextArg eq "limitlines"} {
                set opts(limitlines) $arg
            } elseif {$nextArg eq "maxwidth"} {
                set opts(maxwidth) $arg
            } elseif {$nextArg eq "context"} {
                set ::Pref(context) $arg
            } elseif {$nextArg eq "pivot"} {
                if {$arg >= 1} {
        if {$arg eq "-"} {
                    set ::Pref(pivot) $arg
                }
            } elseif {$nextArg eq "prefix"} {
                set RE [string map [list % $arg] {^.*?\m(%\w+).*$}]
                if {$::Pref(nocase)} {
                    set RE "(?i)$RE"
                }
                lappend ::Pref(preprocess) $RE {\1} ""
            } elseif {$nextArg eq "plugin"} {
                set plugin $arg
            } elseif {$nextArg eq "plugininfo"} {
                set plugininfo $arg
            } elseif {$nextArg eq "plugindump"} {
                set plugindump $arg
            } elseif {[string match "preprocess*" $nextArg]} {
                set side [string range $nextArg 10 end]
                if {[catch {llength $arg} len]} {

            # Allow "-" for stdin patch processing
                } elseif {[llength $arg] % 2 == 1} {

            lappend files "-"
                } else {
                    # FIXA: better validity check
                    foreach {RE sub} $arg {
                        lappend ::Pref(preprocess) $RE $sub $side
                    }
                }
            }
            set nextArg ""
            continue
        }
        # Take care of the special case of RCS style -r<rev>
        if {$arg ne "-review" && [string range $arg 0 1] eq "-r" && \
                [string length $arg] > 2} {
            set opts(doptrev$revNo) [string range $arg 2 end]
                    [string length $arg] > 2} {
            optSet -r [string range $arg 2 end]
            incr revNo
            continue
        }
        # Handle unknowns
        if {![dict exists $::eskil(opts) $arg]} {
        # Try to see if it is an unique abbreviation of an option.
            # Try to see if it is an unique abbreviation of an option.
        # If not, let it fall through to the file check.
        if {[lsearch -exact $allOpts $arg] < 0} {
            set match [allOpts $arg*]
            set match [lsearch -glob -all -inline $allOpts $arg*]
            if {[llength $match] == 1} {
                set arg [lindex $match 0]
            } else {
                # If not, try to put it among files
                cmdLineAddFile files $arg
                continue
            }
        }
        # Flags
        if {[optIsFlag $arg]} {
            set val 1
        } else {
            # Options with values
            incr i
            set val [lindex $::eskil(argv) $i]

        if {$arg eq "-w"} {
            set ::Pref(ignore) "-w"
        } elseif {$arg eq "--help" || $arg eq "-help"} {
            printUsage
            exit
        } elseif {$arg eq "-b"} {
            set ::Pref(ignore) "-b"
        } elseif {$arg eq "-noignore"} {
            set ::Pref(ignore) " "
        } elseif {$arg eq "-i"} {
            set ::Pref(nocase) 1
        } elseif {$arg eq "-nocase"} {
            set ::Pref(nocase) 1
        } elseif {$arg eq "-noempty"} { # FIXA: Add to documentation
            set ::Pref(noempty) 1
        }
        optSet $arg $val
    }

    if {[optIsGiven -help arg] || [optIsGiven --help arg]} {
        printUsage
        exit
    }

    # All options have been parsed, extract them to where they need to go

    # Straight to locals
    set plugin      [optGet -plugin]
    set plugininfo  [optGet -plugininfo]
    set plugindump  [optGet -plugindump]
    set pluginlist  [optGet -pluginlist]
    set pluginallow [optGet -pluginallow]
    set noautodiff  [optGet -nodiff]
    set nocdiff     [optGet -nocdiff]
    set dodir       [optGet -dir]
    set doclip      [optGet -clip]
    set dopatch     [optGet -patch]
    set doreview    [optGet -review]
    set autobrowse  [optGet -browse]
    set foreach     [optGet -foreach]
    set preferedRev "GIT"
    if {[optGet -svn]} {
        set preferedRev "SVN"
    } elseif {[optGet -cvs]} {
        set preferedRev "CVS"
    }

    # TODO: Handle mutually exclusive options in optparsing directly?
    if {[optIsGiven -w arg]} {
        set ::Pref(ignore) "-w"
    } elseif {[optIsGiven -b arg]} {
        set ::Pref(ignore) "-b"
    } elseif {[optIsGiven -noignore arg]} {
        set ::Pref(ignore) " "
        } elseif {$arg eq "-pivot"} { # FIXA: Add to documentation
            set nextArg pivot
        } elseif {$arg eq "-nodigit"} {
            set ::Pref(nodigit) 1
        } 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 "-preprocessleft"} {
            set nextArg preprocessleft
        } elseif {$arg eq "-preprocessright"} {
            set nextArg preprocessright
        } elseif {$arg eq "-plugin"} {
            set nextArg "plugin"
        } elseif {$arg eq "-plugininfo"} {
            set nextArg "plugininfo"
    }
    if {[optIsGiven -noparse arg]} {
        set ::Pref(parse) 0
    } elseif {[optIsGiven -line arg]} {
        set ::Pref(parse) 1
    } elseif {[optIsGiven -smallblock arg]} {
        set ::Pref(parse) 2
    } elseif {[optIsGiven -block arg]} {
        set ::Pref(parse) 3
    }
    if {[optIsGiven -char arg]} {
        set ::Pref(lineparsewords) 0
    } elseif {[optIsGiven -word arg]} {
        set ::Pref(lineparsewords) 1
    }

    # These directly correspond to Pref settings
    set apa {
        -printFont printFont
        -context   context
        -i nocase -nocase nocase
        -noempty   noempty
        -nodigit   nodigit
        -nokeyword dir,ignorekey
        -fine      finegrainchunks
    }
    foreach {opt elem} $apa {
        if {[optIsGiven $opt arg]} {
            set ::Pref($elem) $arg
        }
    }

    # These directly correspond to opts settings
    set apa {
        } elseif {$arg eq "-plugindump"} {
            set nextArg "plugindump"
        -limit limitlines
        } elseif {$arg eq "-pluginlist"} {
            set pluginlist 1
        } elseif {$arg eq "-pluginallow"} {
            set pluginallow 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"} {
            set ::Pref(parse) 2
        } elseif {$arg eq "-block"} {
            set ::Pref(parse) 3
        } elseif {$arg eq "-char"} {
            set ::Pref(lineparsewords) 0
        } elseif {$arg eq "-word"} {
            set ::Pref(lineparsewords) 1
        } elseif {$arg eq "-2nd"} { # Deprecated
            #set ::Pref(extralineparse) 1
        } elseif {$arg eq "-no2nd"} { # Deprecated
            #set ::Pref(extralineparse) 0
        } elseif {$arg eq "-limit"} {
            set nextArg limitlines
        -maxwidth maxwidth
    }
    foreach {opt elem} $apa {
        if {[optIsGiven $opt arg]} {
            set opts($elem) $arg
        }
    }

    # These directly correspond to ::eskil settings
    set apa {
        -nonewline  ignorenewline 1
        -nonewline+ ignorenewline 2
        -close      autoclose 1
        -debug      debug 1
    }
    foreach {opt elem val} $apa {
        if {[optIsGiven $opt arg]} {
            set ::eskil($elem) $val
        }
    }

    # Options that need individual checking/processing
    if {[optIsGiven -o arg]} {
        set opts(mergeFile) [file join [pwd] $arg]
    }
    if {[optIsGiven -a arg]} {
        set opts(ancestorFile) [file join [pwd] $arg]
        # Default is no ignore on three-way merge
        set ::Pref(ignore) " "
    }
    if {[optIsGiven -sep arg]} {
        # Handle if separator is given e.g. as '\t'
        set opts(separator) [subst -nocommands -novariables $arg]
    }
    if {[optIsGiven -print arg] || [optIsGiven -printpdf arg]} {
        set opts(printFile) [file join [pwd] $arg]
        set opts(printFileCmd) 1
    }
    if {[optIsGiven -conflict arg]} {
        set opts(mode) "conflict"
        # Conflict implies foreach
        set foreach 1
    }
    if {[optIsGiven -table arg]} {
        set opts(view) "table"
    }
    if {[optIsGiven -printHeaderSize arg]} {
        if {![string is double -strict $arg] || $arg <= 0} {
            puts "Argument -printHeaderSize must be a positive number"
            exit
        } elseif {$arg eq "-maxwidth"} {
            set nextArg maxwidth
        } elseif {$arg eq "-nodiff"} {
        }
        set ::Pref(printHeaderSize) $arg
    }
    if {[optIsGiven -printCharsPerLine arg]} {
            set noautodiff 1
        } elseif {$arg eq "-nocdiff"} {
            set nocdiff 1
        } elseif {$arg eq "-dir"} {
            set dodir 1
        } elseif {$arg eq "-clip"} {
            set doclip 1
        } elseif {$arg eq "-table"} {
            set opts(view) "table"
        } elseif {$arg eq "-patch"} {
            set dopatch 1
        } elseif {$arg eq "-review"} {
        if {![string is double -strict $arg] || $arg <= 0} {
            puts "Argument -printCharsPerLine must be a positive number"
            exit
        }
        set ::Pref(printCharsPerLine) $arg
    }
    if {[optIsGiven -printPaper arg]} {
        package require pdf4tcl
        if {[llength [pdf4tcl::getPaperSize $arg]] != 2} {
            puts "Argument -printPaper must be a valid paper size"
            puts "Valid paper sizes:"
            puts [join [lsort -dictionary [pdf4tcl::getPaperSizeList]] \n]
            exit
        }
        set ::Pref(printPaper) $arg
    }
    if {[optIsGiven -printColorChange arg]} {
        ValidatePdfColor $arg -printColorChange
        set ::Pref(printColorChange) $arg
    }
    if {[optIsGiven -printColorOld arg]} {
        ValidatePdfColor $arg -printColorOld
        set ::Pref(printColorNew1) $arg
    }
    if {[optIsGiven -printColorNew arg]} {
        ValidatePdfColor $arg -printColorNew
        set ::Pref(printColorNew2) $arg
    }
    if {[optIsGiven -pivot arg]} {
            set doreview 1
        } elseif {$arg eq "-browse"} {
            set autobrowse 1
        } elseif {$arg eq "-foreach"} {
            set foreach 1
        } elseif {$arg eq "-nonewline"} {
            set ::eskil(ignorenewline) 1
        } elseif {$arg eq "-nonewline+"} {
            set ::eskil(ignorenewline) 2
        } elseif {$arg eq "-close"} {
        if {$arg >= 1} {
            set ::Pref(pivot) $arg
        }
    }
    if {[optIsGiven -prefix arg]} {
        foreach apa $arg {
            set RE [string map [list % $apa] {^.*?\m(%\w+).*$}]
            if {$::Pref(nocase)} {
                set RE "(?i)$RE"
            }
            lappend ::Pref(preprocess) $RE {\1} ""
        }
    }
    if {[optIsGiven -preprocess arg]} {
        # FIXA: better validity check
        foreach apa $arg {
            foreach {RE sub} $apa {
                lappend ::Pref(preprocess) $RE $sub ""
            }
        }
    }
    if {[optIsGiven -preprocessleft arg]} {
            set ::eskil(autoclose) 1
        } elseif {$arg eq "-conflict"} {
        # FIXA: better validity check
        foreach apa $arg {
            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 \
            foreach {RE sub} $apa {
                lappend ::Pref(preprocess) $RE $sub left
            }
        }
    }
    if {[optIsGiven -preprocessright arg]} {
        # FIXA: better validity check
        foreach apa $arg {
            foreach {RE sub} $apa {
                lappend ::Pref(preprocess) $RE $sub right
            }
        }
    }
    # Handle list of revisions
    if {[optIsGiven -r arg]} {
        set revNo 1
        foreach rev $arg {
                -printColorChange -printColorOld -printColorNew -printFont}} {
            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
            }
            set opts(doptrev$revNo) $rev
            incr revNo
        }
    }
    if {[optGet -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 "-sep"} {
            set nextArg separator
        } 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
            }
        }
    }

    }
    # Option handling done. Lets get started.

    Init

    if {$nocdiff} {
        DisableDiffUtilC
    }

4532
4533
4534
4535
4536
4537
4538
4539

4540
4541
4542
4543
4544
4545
4546
4624
4625
4626
4627
4628
4629
4630

4631
4632
4633
4634
4635
4636
4637
4638







-
+







        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

    # It is preferable to see the end if the rev string is too long
    $::widgets($top,rev1) xview end
    $::widgets($top,rev2) xview end