cmdr
Check-in [86ce9388c1]
Not logged in
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to tclconference@googlegroups.com
or submit via the online form by Sep 9.

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

Overview
Comment:Design mistake --- Closing --- Extended handling of "fail-unknown-thing" (fut) with hooks allowing this general code to ask for custom messaging. Directly from the parameter, indirectly from the validation type. Whose "validate" method is where "fail-unknown-thing" got called from. Which means that we have a possible alternative solution which does not go through such a convoluted circle: New convenience function, an extension of "fail-unknown-thing" which simply takes the custom message as a parameter. And we can write more functions of this type then, which take ranges, dicts, etc. and operate on these for rendering, or a possible user-choice to fix the bad value. Saving the current state before making a decision --- Trunk went forward with the alternate approach, see [3305575764].
Timelines: family | ancestors | x-fut-acceptable
Files: files | file ages | folders
SHA1:86ce9388c1a27b495ca30e9c47beb96903895394
User & Date: andreask 2015-06-26 21:58:26
Original Comment: Extended handling of "fail-unknown-thing" (fut) with hooks allowing this general code to ask for custom messaging. Directly from the parameter, indirectly from the validation type. Whose "validate" method is where "fail-unknown-thing" got called from. Which means that we have a possible alternate which does not such a convoluted circle: New convenience function, an extension of "fail-unknown-thing" which simply gets the custom message directly as a parameter. And we can do other functions of this type then, which take ranges, dicts, etc. and operate on these for rendering, or a possible user-choice to fix the bad value. Saving the current state before making a decision.
Context
2015-06-26
21:58
Design mistake --- Closing --- Extended handling of "fail-unknown-thing" (fut) with hooks allowing this general code to ask for custom messaging. Directly from the parameter, indirectly from the validation type. Whose "validate" method is where "fail-unknown-thing" got called from. Which means that we have a possible alternative solution which does not go through such a convoluted circle: New convenience function, an extension of "fail-unknown-thing" which simply takes the custom message as a parameter. And we can write more functions of this type then, which take ranges, dicts, etc. and operate on these for rendering, or a possible user-choice to fix the bad value. Saving the current state before making a decision --- Trunk went forward with the alternate approach, see [3305575764]. Closed-Leaf check-in: 86ce9388c1 user: andreask tags: x-fut-acceptable
2015-05-12
22:15
config, color - Bump version numbers, due to their recent changes. check-in: 4f21251865 user: aku tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to parameter.tcl.

808
809
810
811
812
813
814







815
816
817
818
819
820
821
....
1295
1296
1297
1298
1299
1300
1301
1302
	}

	set myhasstring yes
	my forget
	my RunWhenSetHooks
	return
    }








    method accept {x} {
	debug.cmdr/parameter {}
	try {
	    my ValueRelease [{*}$myvalidate validate [self] $x]
	    # If that was ok it has to be released also!
	    # XXX Or should we maybe immediately cache it for 'value'?
................................................................................
	myisundefined mynopromote myhasinverted

    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::parameter 1.5







>
>
>
>
>
>
>







 







|
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
....
1302
1303
1304
1305
1306
1307
1308
1309
	}

	set myhasstring yes
	my forget
	my RunWhenSetHooks
	return
    }

    method acceptable {} {
	debug.cmdr/parameter {}
	# Ask the validation type of the parameter for text about
	# acceptable values.
	return [{*}$myvalidate acceptable [self]]
    }

    method accept {x} {
	debug.cmdr/parameter {}
	try {
	    my ValueRelease [{*}$myvalidate validate [self] $x]
	    # If that was ok it has to be released also!
	    # XXX Or should we maybe immediately cache it for 'value'?
................................................................................
	myisundefined mynopromote myhasinverted

    # # ## ### ##### ######## #############
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::parameter 1.6

Changes to validate.tcl.

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
...
132
133
134
135
136
137
138
139
140
141
142





143
144
145
146
147
148
149
...
197
198
199
200
201
202
203
204
205
206
207






208
209
210
211
212
213
214
...
226
227
228
229
230
231
232
233
234
235
236

237
238





239
240
241
242
243
244
245
...
261
262
263
264
265
266
267
268
269
270
271

272
273





274
275
276
277
278
279
280
...
297
298
299
300
301
302
303
304
305
306
307






308
309
310
311
312
313
314
...
327
328
329
330
331
332
333
334
335
336
337

338
339





340
341
342
343
344
345
346
...
364
365
366
367
368
369
370
371
372
373
374






375
376
377
378
379
380
381
...
393
394
395
396
397
398
399
400
401
402
403

404
405





406
407
408
409
410
411
412
...
429
430
431
432
433
434
435
436
437
438
439






440
441
442
443
444
445
446
...
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
...
501
502
503
504
505
506
507
508
509
510
511

512
513





514
515
516
517
518
519
520
...
535
536
537
538
539
540
541
542
543
debug define cmdr/validate
debug level  cmdr/validate
debug prefix cmdr/validate {[debug caller] | }

# # ## ### ##### ######## ############# #####################

namespace eval ::cmdr::validate::boolean {
    namespace export default validate complete release
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-enum
}

proc ::cmdr::validate::boolean::release  {p x} { return }
proc ::cmdr::validate::boolean::default  {p}  {
    debug.cmdr/validate {}
    return no
}






proc ::cmdr::validate::boolean::complete {p x} {
    debug.cmdr/validate {} 10
    return [complete-enum {yes no false true on off 0 1} 1 $x]
}

proc ::cmdr::validate::boolean::validate {p x} {
................................................................................
    fail $p DOUBLE "a double" $x
}

# # ## ### ##### ######## ############# #####################
## Any double in [0,100]

namespace eval ::cmdr::validate::percent {
    namespace export default validate complete release
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
}






proc ::cmdr::validate::percent::release  {p x} { return }
proc ::cmdr::validate::percent::default  {p}  {
    debug.cmdr/validate {}
    return 0
}
proc ::cmdr::validate::percent::complete {p x} {
................................................................................
proc ::cmdr::validate::str::complete {p x} { debug.cmdr/validate {} 10 ; return {} }
proc ::cmdr::validate::str::validate {p x} { debug.cmdr/validate {}    ; return $x }

# # ## ### ##### ######## ############# #####################
## File, existing and readable

namespace eval ::cmdr::validate::rfile {
    namespace export default validate complete release
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob






}

proc ::cmdr::validate::rfile::release  {p x} { return }
proc ::cmdr::validate::rfile::default  {p}   { return {} }
proc ::cmdr::validate::rfile::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rfile::Ok $x
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## File, existing and writable

namespace eval ::cmdr::validate::wfile {
    namespace export default validate complete release
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob

    namespace import ::cmdr::validate::common::ok-directory
}






proc ::cmdr::validate::wfile::release  {p x} { return }
proc ::cmdr::validate::wfile::default  {p}   { return {} }
proc ::cmdr::validate::wfile::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::wfile::Ok $x
}
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## File, existing and read/writable

namespace eval ::cmdr::validate::rwfile {
    namespace export default validate complete release
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob

    namespace import ::cmdr::validate::common::ok-directory
}






proc ::cmdr::validate::rwfile::release  {p x} { return }
proc ::cmdr::validate::rwfile::default  {p}   { return {} }
proc ::cmdr::validate::rwfile::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rwfile::Ok $x
}
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Directory, existing and readable.

namespace eval ::cmdr::validate::rdirectory {
    namespace export default validate complete release
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob






}

proc ::cmdr::validate::rdirectory::release  {p x} { return }
proc ::cmdr::validate::rdirectory::default  {p}   { return {} }
proc ::cmdr::validate::rdirectory::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rdirectory::Ok $x
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Directory, existing and read/writable.

namespace eval ::cmdr::validate::rwdirectory {
    namespace export default validate complete release
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob

    namespace import ::cmdr::validate::common::ok-directory
}






proc ::cmdr::validate::rwdirectory::release  {p x} { return }
proc ::cmdr::validate::rwdirectory::default  {p}   { return {} }
proc ::cmdr::validate::rwdirectory::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rwdirectory::Ok $x
}
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Any path, existing and readable.

namespace eval ::cmdr::validate::rpath {
    namespace export default validate complete release
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob






}

proc ::cmdr::validate::rpath::release  {p x} { return }
proc ::cmdr::validate::rpath::default  {p}   { return {} }
proc ::cmdr::validate::rpath::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rpath::Ok $x
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Any path, existing and read/writable.

namespace eval ::cmdr::validate::rwpath {
    namespace export default validate complete release
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob

    namespace import ::cmdr::validate::common::ok-directory
}






proc ::cmdr::validate::rwpath::release  {p x} { return }
proc ::cmdr::validate::rwpath::default  {p}   { return {} }
proc ::cmdr::validate::rwpath::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rwpath::Ok $x
}
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Channel, for existing and readable file. Defaults to stdin.

namespace eval ::cmdr::validate::rchan {
    namespace export default validate complete release
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob






}

proc ::cmdr::validate::rchan::release  {p x} {
    if {$x eq "stdin"} return
    close $x
    return
}
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Channel, for existing and writable file. Defaults to stdout.

namespace eval ::cmdr::validate::wchan {
    namespace export default validate complete release
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob

    namespace import ::cmdr::validate::common::ok-directory
}






proc ::cmdr::validate::wchan::release  {p x} {
    if {$x eq "stdout"} return
    close $x
    return
}

proc ::cmdr::validate::wchan::default  {p}   { return stdout }
proc ::cmdr::validate::wchan::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::wchan::Ok $x
}
proc ::cmdr::validate::wchan::validate {p x} {
    debug.cmdr/validate {}
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Channel, for existing and read/writable file. No default.

namespace eval ::cmdr::validate::rwchan {
    namespace export default validate complete release
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob

    namespace import ::cmdr::validate::common::ok-directory
}






proc ::cmdr::validate::rwchan::release  {p x} { close $x }
proc ::cmdr::validate::rwchan::default  {p}   { return {} }
proc ::cmdr::validate::rwchan::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rwchan::Ok $x
}
................................................................................
    if {![file readable $path]} {return 0}
    if {![file writable $path]} {return 0}
    return 1
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::validate 1.3.1
return







|










>
>
>
>
>







 







|



>
>
>
>
>







 







|



>
>
>
>
>
>







 







|



>


>
>
>
>
>







 







|



>


>
>
>
>
>







 







|



>
>
>
>
>
>







 







|



>


>
>
>
>
>







 







|



>
>
>
>
>
>







 







|



>


>
>
>
>
>







 







|



>
>
>
>
>
>







 







|



>


>
>
>
>
>






>







 







|



>


>
>
>
>
>







 







|

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
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
...
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
267
...
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
...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
...
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
...
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
...
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
...
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
...
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
...
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
...
606
607
608
609
610
611
612
613
614
debug define cmdr/validate
debug level  cmdr/validate
debug prefix cmdr/validate {[debug caller] | }

# # ## ### ##### ######## ############# #####################

namespace eval ::cmdr::validate::boolean {
    namespace export default validate complete release acceptable
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-enum
}

proc ::cmdr::validate::boolean::release  {p x} { return }
proc ::cmdr::validate::boolean::default  {p}  {
    debug.cmdr/validate {}
    return no
}

proc ::cmdr::validate::boolean::acceptable {p} {
    debug.cmdr/validate {} 10
    return "Expected one of: yes, no, false, true, on, off, 0, or 1"
}

proc ::cmdr::validate::boolean::complete {p x} {
    debug.cmdr/validate {} 10
    return [complete-enum {yes no false true on off 0 1} 1 $x]
}

proc ::cmdr::validate::boolean::validate {p x} {
................................................................................
    fail $p DOUBLE "a double" $x
}

# # ## ### ##### ######## ############# #####################
## Any double in [0,100]

namespace eval ::cmdr::validate::percent {
    namespace export default validate complete release acceptable
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
}

proc ::cmdr::validate::percent::acceptable {p} {
    debug.cmdr/validate {} 10
    return "Expected a value in the range \[0...100\]."
}

proc ::cmdr::validate::percent::release  {p x} { return }
proc ::cmdr::validate::percent::default  {p}  {
    debug.cmdr/validate {}
    return 0
}
proc ::cmdr::validate::percent::complete {p x} {
................................................................................
proc ::cmdr::validate::str::complete {p x} { debug.cmdr/validate {} 10 ; return {} }
proc ::cmdr::validate::str::validate {p x} { debug.cmdr/validate {}    ; return $x }

# # ## ### ##### ######## ############# #####################
## File, existing and readable

namespace eval ::cmdr::validate::rfile {
    namespace export default validate complete release acceptable
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob
    namespace import ::cmdr::validate::common::one-path
}

proc ::cmdr::validate::rfile::acceptable {p} {
    debug.cmdr/validate {} 10
    return [one-path "readable file" ::cmdr::validate::rfile::Ok]
}

proc ::cmdr::validate::rfile::release  {p x} { return }
proc ::cmdr::validate::rfile::default  {p}   { return {} }
proc ::cmdr::validate::rfile::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rfile::Ok $x
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## File, existing and writable

namespace eval ::cmdr::validate::wfile {
    namespace export default validate complete release acceptable
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob
    namespace import ::cmdr::validate::common::one-path
    namespace import ::cmdr::validate::common::ok-directory
}

proc ::cmdr::validate::wfile::acceptable {p} {
    debug.cmdr/validate {} 10
    return [one-path "writable file" ::cmdr::validate::wfile::Ok]
}

proc ::cmdr::validate::wfile::release  {p x} { return }
proc ::cmdr::validate::wfile::default  {p}   { return {} }
proc ::cmdr::validate::wfile::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::wfile::Ok $x
}
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## File, existing and read/writable

namespace eval ::cmdr::validate::rwfile {
    namespace export default validate complete release acceptable
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob
    namespace import ::cmdr::validate::common::one-path
    namespace import ::cmdr::validate::common::ok-directory
}

proc ::cmdr::validate::rwfile::acceptable {p} {
    debug.cmdr/validate {} 10
    return [one-path "read/writeable file" ::cmdr::validate::rwfile::Ok]
}

proc ::cmdr::validate::rwfile::release  {p x} { return }
proc ::cmdr::validate::rwfile::default  {p}   { return {} }
proc ::cmdr::validate::rwfile::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rwfile::Ok $x
}
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Directory, existing and readable.

namespace eval ::cmdr::validate::rdirectory {
    namespace export default validate complete release acceptable
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob
    namespace import ::cmdr::validate::common::one-path
}

proc ::cmdr::validate::rdirectory::acceptable {p} {
    debug.cmdr/validate {} 10
    return [one-path "readable directory" ::cmdr::validate::rdirectory::Ok]
}

proc ::cmdr::validate::rdirectory::release  {p x} { return }
proc ::cmdr::validate::rdirectory::default  {p}   { return {} }
proc ::cmdr::validate::rdirectory::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rdirectory::Ok $x
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Directory, existing and read/writable.

namespace eval ::cmdr::validate::rwdirectory {
    namespace export default validate complete release acceptable
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob
    namespace import ::cmdr::validate::common::one-path
    namespace import ::cmdr::validate::common::ok-directory
}

proc ::cmdr::validate::rwdirectory::acceptable {p} {
    debug.cmdr/validate {} 10
    return [one-path "read/writable directory" ::cmdr::validate::rwdirectory::Ok]
}

proc ::cmdr::validate::rwdirectory::release  {p x} { return }
proc ::cmdr::validate::rwdirectory::default  {p}   { return {} }
proc ::cmdr::validate::rwdirectory::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rwdirectory::Ok $x
}
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Any path, existing and readable.

namespace eval ::cmdr::validate::rpath {
    namespace export default validate complete release acceptable
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob
    namespace import ::cmdr::validate::common::one-path
}

proc ::cmdr::validate::rpath::acceptable {p} {
    debug.cmdr/validate {} 10
    return [one-path "readable path" ::cmdr::validate::rpath::Ok]
}

proc ::cmdr::validate::rpath::release  {p x} { return }
proc ::cmdr::validate::rpath::default  {p}   { return {} }
proc ::cmdr::validate::rpath::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rpath::Ok $x
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Any path, existing and read/writable.

namespace eval ::cmdr::validate::rwpath {
    namespace export default validate complete release acceptable
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob
    namespace import ::cmdr::validate::common::one-path
    namespace import ::cmdr::validate::common::ok-directory
}

proc ::cmdr::validate::rwpath::acceptable {p} {
    debug.cmdr/validate {} 10
    return [one-path "read/writable path" ::cmdr::validate::rwpath::Ok]
}

proc ::cmdr::validate::rwpath::release  {p x} { return }
proc ::cmdr::validate::rwpath::default  {p}   { return {} }
proc ::cmdr::validate::rwpath::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rwpath::Ok $x
}
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Channel, for existing and readable file. Defaults to stdin.

namespace eval ::cmdr::validate::rchan {
    namespace export default validate complete release acceptable
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob
    namespace import ::cmdr::validate::common::one-path
}

proc ::cmdr::validate::rchan::acceptable {p} {
    debug.cmdr/validate {} 10
    return [one-path "readable file" ::cmdr::validate::rchan::Ok]
}

proc ::cmdr::validate::rchan::release  {p x} {
    if {$x eq "stdin"} return
    close $x
    return
}
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Channel, for existing and writable file. Defaults to stdout.

namespace eval ::cmdr::validate::wchan {
    namespace export default validate complete release acceptable
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob
    namespace import ::cmdr::validate::common::one-path
    namespace import ::cmdr::validate::common::ok-directory
}

proc ::cmdr::validate::wchan::acceptable {p} {
    debug.cmdr/validate {} 10
    return [one-path "writable file" ::cmdr::validate::wchan::Ok]
}

proc ::cmdr::validate::wchan::release  {p x} {
    if {$x eq "stdout"} return
    close $x
    return
}

proc ::cmdr::validate::wchan::default  {p}   { return stdout }
proc ::cmdr::validate::wchan::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::wchan::Ok $x
}
proc ::cmdr::validate::wchan::validate {p x} {
    debug.cmdr/validate {}
................................................................................
    return 1
}

# # ## ### ##### ######## ############# #####################
## Channel, for existing and read/writable file. No default.

namespace eval ::cmdr::validate::rwchan {
    namespace export default validate complete release acceptable
    namespace ensemble create
    namespace import ::cmdr::validate::common::fail
    namespace import ::cmdr::validate::common::complete-glob
    namespace import ::cmdr::validate::common::one-path
    namespace import ::cmdr::validate::common::ok-directory
}

proc ::cmdr::validate::rwchan::acceptable {p} {
    debug.cmdr/validate {} 10
    return [one-path "read/writable file" ::cmdr::validate::rwchan::Ok]
}

proc ::cmdr::validate::rwchan::release  {p x} { close $x }
proc ::cmdr::validate::rwchan::default  {p}   { return {} }
proc ::cmdr::validate::rwchan::complete {p x} {
    debug.cmdr/validate {} 10
    complete-glob ::cmdr::validate::rwchan::Ok $x
}
................................................................................
    if {![file readable $path]} {return 0}
    if {![file writable $path]} {return 0}
    return 1
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::validate 1.4
return

Changes to vcommon.tcl.

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
..
65
66
67
68
69
70
71











72


73


74
75
76
77
78
79
80
..
95
96
97
98
99
100
101




































102
103
104
105
106
107
108
...
188
189
190
191
192
193
194
195
196
    namespace ensemble create
}

namespace eval ::cmdr::validate::common {
    namespace export \
	complete-enum complete-glob complete-substr \
	ok-directory lead-in fail fail-unknown-thing \
	fail-known-thing
    namespace ensemble create
}

# # ## ### ##### ######## ############# #####################

debug define cmdr/validate/common
debug level  cmdr/validate/common
................................................................................

proc ::cmdr::validate::common::fail-unknown-thing {p code type x {context {}}} {
    # Specific failure for a named thing: Expected existence, found it missing.
    debug.cmdr/validate/common {}

    append msg "Found a problem with [$p type] \"[$p the-name]\":"
    append msg " [lead-in $type] \"$x\" does not exist$context."











    append msg " Please use a different value."





    return -code error -errorcode [list CMDR VALIDATE {*}$code] $msg
}

proc ::cmdr::validate::common::fail-known-thing {p code type x {context {}}} {
    # Specific failure for a named thing: Expected non-existence, found a definition.
    debug.cmdr/validate/common {}

................................................................................
    } elseif {[string match {[aeiouAEIOU]*} $type]} {
	set lead {An }
    } else {
	set lead {A }
    }
    return $lead$type
}





































# # ## ### ##### ######## ############# #####################

proc ::cmdr::validate::common::complete-enum {choices nocase buffer} {
    # As a helper function for command completion printing anything
    # here would mix with the output of linenoise. Do that only on
    # explicit request (level 10).
................................................................................
    if {![file isdirectory $path]} {return 0}
    if {![file writable    $path]} {return 0}
    return 1
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::validate::common 1.2
return







|







 







>
>
>
>
>
>
>
>
>
>
>
|
>
>

>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
..
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
...
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
...
239
240
241
242
243
244
245
246
247
    namespace ensemble create
}

namespace eval ::cmdr::validate::common {
    namespace export \
	complete-enum complete-glob complete-substr \
	ok-directory lead-in fail fail-unknown-thing \
	fail-known-thing one-of one-path expected
    namespace ensemble create
}

# # ## ### ##### ######## ############# #####################

debug define cmdr/validate/common
debug level  cmdr/validate/common
................................................................................

proc ::cmdr::validate::common::fail-unknown-thing {p code type x {context {}}} {
    # Specific failure for a named thing: Expected existence, found it missing.
    debug.cmdr/validate/common {}

    append msg "Found a problem with [$p type] \"[$p the-name]\":"
    append msg " [lead-in $type] \"$x\" does not exist$context."

    # Ping the parameter for knowledge of acceptable values and use
    # the information when available. Fall back to a generic text if
    # the parameter doesn't know anything.
    if {[catch {
	set acceptable [$p acceptable]
	# This calls, indirectly, on method 'acceptable' of p's
	# validation type.
    }]} {
	debug.cmdr/validate/common {fail accept: $::errorInfo}

	append msg " Please use a different value."
    } else {
	debug.cmdr/validate/common {accept: $acceptable}

	append msg " " $acceptable
    }
    return -code error -errorcode [list CMDR VALIDATE {*}$code] $msg
}

proc ::cmdr::validate::common::fail-known-thing {p code type x {context {}}} {
    # Specific failure for a named thing: Expected non-existence, found a definition.
    debug.cmdr/validate/common {}

................................................................................
    } elseif {[string match {[aeiouAEIOU]*} $type]} {
	set lead {An }
    } else {
	set lead {A }
    }
    return $lead$type
}

proc ::cmdr::validate::common::one-path {label filter} {
    set matches [complete-glob $filter *]
    if {![llength $matches]} {
	return "No ${label} found here."
    }
    return "Expected one of\n[one-of $matches yes]"
}

proc ::cmdr::validate::common::one-of {enum {multi no}} {
    if {$multi} {
	set n [string length [expr {1+[llength $enum]}]]
	set m {}
	set i 0
	foreach w $enum { incr i ; append m "[format %${n}d $i]. $w\n" }
    } elseif {[llength $enum] < 2} {
	set m "\"[lindex $enum 0]\""
    } else {
	set m {}
	foreach w [lrange $enum 0 end-1] {
	    append m "\"$w\", "
	}
	append m "or \"[lindex $enum end]\""
    }
    return $m
}

proc ::cmdr::validate::common::expected {enum} {
    if {![llength $enum]} {
	return "Nothing acceptable found"
    }
    set multi [expr {[llength $enum] <= 20}]
    set sep [expr {$multi ? "\n" : ": "}]
    set sfx [expr {$multi ? "" : "."}]
    return "Expected one of$sep[one-of $enum $multi]$sfx"
}

# # ## ### ##### ######## ############# #####################

proc ::cmdr::validate::common::complete-enum {choices nocase buffer} {
    # As a helper function for command completion printing anything
    # here would mix with the output of linenoise. Do that only on
    # explicit request (level 10).
................................................................................
    if {![file isdirectory $path]} {return 0}
    if {![file writable    $path]} {return 0}
    return 1
}

# # ## ### ##### ######## ############# #####################
## Ready
package provide cmdr::validate::common 1.3
return