1
- use std:: collections:: HashMap ;
2
1
use std:: str:: FromStr ;
3
2
use std:: sync:: { Arc , Mutex } ;
4
3
use std:: time:: Duration ;
@@ -16,14 +15,9 @@ use scru128::Scru128Id;
16
15
use crate :: error:: Error ;
17
16
use crate :: nu;
18
17
use crate :: nu:: commands;
19
- use crate :: nu:: util:: value_to_json;
20
- use crate :: store:: { FollowOption , Frame , ReadOptions , Store , TTL } ;
21
-
22
- #[ derive( Clone , Debug , Serialize , Deserialize , Default ) ]
23
- pub struct ReturnOptions {
24
- pub suffix : Option < String > ,
25
- pub ttl : Option < TTL > ,
26
- }
18
+ use crate :: nu:: value_to_json;
19
+ use crate :: nu:: ReturnOptions ;
20
+ use crate :: store:: { FollowOption , Frame , ReadOptions , Store } ;
27
21
28
22
#[ derive( Clone ) ]
29
23
pub struct Handler {
@@ -38,7 +32,6 @@ pub struct Handler {
38
32
#[ derive( Clone , Debug ) ]
39
33
struct HandlerConfig {
40
34
resume_from : ResumeFrom ,
41
- modules : HashMap < String , String > ,
42
35
pulse : Option < u64 > ,
43
36
return_options : Option < ReturnOptions > ,
44
37
}
@@ -82,22 +75,10 @@ impl Handler {
82
75
) ) ,
83
76
] ) ?;
84
77
85
- let ( mut run, mut config) = parse_handler_configuration_script ( & mut engine, & expression) ?;
86
-
87
- // Load modules and reparse if needed
88
- if !config. modules . is_empty ( ) {
89
- for ( name, content) in & config. modules {
90
- tracing:: debug!( "Loading module '{}'" , name) ;
91
- engine
92
- . add_module ( name, content)
93
- . map_err ( |e| format ! ( "Failed to load module '{}': {}" , name, e) ) ?;
94
- }
95
-
96
- // we need to re-parse the expression after loading modules, so that the closure has access
97
- // to the additional modules: not the best, but I can't see a better way
98
- ( run, config) = parse_handler_configuration_script ( & mut engine, & expression) ?;
99
- }
78
+ // Parse configuration (this will handle module loading internally)
79
+ let ( run, config) = parse_handler_configuration_script ( & mut engine, & expression) ?;
100
80
81
+ // Validate the closure signature
101
82
let block = engine. state . get_block ( run. block_id ) ;
102
83
if block. signature . required_positional . len ( ) != 1 {
103
84
return Err ( format ! (
@@ -423,41 +404,17 @@ use nu_protocol::debugger::WithoutDebug;
423
404
use nu_protocol:: engine:: { Closure , Stack , StateWorkingSet } ;
424
405
use nu_protocol:: PipelineData ;
425
406
426
- use nu_protocol:: format_shell_error;
427
- use nu_protocol:: ShellError ;
428
-
429
407
fn parse_handler_configuration_script (
430
408
engine : & mut nu:: Engine ,
431
409
script : & str ,
432
410
) -> Result < ( Closure , HandlerConfig ) , Error > {
433
- let mut working_set = StateWorkingSet :: new ( & engine. state ) ;
411
+ // Parse common options first (includes run, modules, return_options)
412
+ let common_options = nu:: parse_config ( engine, script) ?;
434
413
414
+ // Parse handler-specific options
415
+ let mut working_set = StateWorkingSet :: new ( & engine. state ) ;
435
416
let block = parse ( & mut working_set, None , script. as_bytes ( ) , false ) ;
436
417
437
- // Handle parse errors
438
- if let Some ( err) = working_set. parse_errors . first ( ) {
439
- let shell_error = ShellError :: GenericError {
440
- error : "Parse error" . into ( ) ,
441
- msg : format ! ( "{:?}" , err) ,
442
- span : Some ( err. span ( ) ) ,
443
- help : None ,
444
- inner : vec ! [ ] ,
445
- } ;
446
- return Err ( Error :: from ( format_shell_error ( & working_set, & shell_error) ) ) ;
447
- }
448
-
449
- // Handle compile errors
450
- if let Some ( err) = working_set. compile_errors . first ( ) {
451
- let shell_error = ShellError :: GenericError {
452
- error : "Compile error" . into ( ) ,
453
- msg : format ! ( "{:?}" , err) ,
454
- span : None ,
455
- help : None ,
456
- inner : vec ! [ ] ,
457
- } ;
458
- return Err ( Error :: from ( format_shell_error ( & working_set, & shell_error) ) ) ;
459
- }
460
-
461
418
engine. state . merge_delta ( working_set. render ( ) ) ?;
462
419
463
420
let mut stack = Stack :: new ( ) ;
@@ -466,19 +423,11 @@ fn parse_handler_configuration_script(
466
423
& mut stack,
467
424
& block,
468
425
PipelineData :: empty ( ) ,
469
- )
470
- . map_err ( |err| {
471
- let working_set = nu_protocol:: engine:: StateWorkingSet :: new ( & engine. state ) ;
472
- Error :: from ( nu_protocol:: format_shell_error ( & working_set, & err) )
473
- } ) ?;
426
+ ) ?;
474
427
475
428
let config = result. into_value ( nu_protocol:: Span :: unknown ( ) ) ?;
476
429
477
- let run = config
478
- . get_data_by_key ( "run" )
479
- . ok_or ( "No 'run' field found in handler configuration" ) ?
480
- . into_closure ( ) ?;
481
-
430
+ // Parse resume_from (specific to handlers)
482
431
let resume_from = match config. get_data_by_key ( "resume_from" ) {
483
432
Some ( val) => {
484
433
let resume_str = val. as_str ( ) . map_err ( |_| "resume_from must be a string" ) ?;
@@ -494,59 +443,21 @@ fn parse_handler_configuration_script(
494
443
None => ResumeFrom :: default ( ) ,
495
444
} ;
496
445
497
- let modules = match config. get_data_by_key ( "modules" ) {
498
- Some ( val) => {
499
- let record = val. as_record ( ) . map_err ( |_| "modules must be a record" ) ?;
500
- record
501
- . iter ( )
502
- . map ( |( name, content) | {
503
- let content = content
504
- . as_str ( )
505
- . map_err ( |_| format ! ( "module '{}' content must be a string" , name) ) ?;
506
- Ok ( ( name. to_string ( ) , content. to_string ( ) ) )
507
- } )
508
- . collect :: < Result < HashMap < _ , _ > , Error > > ( ) ?
509
- }
510
- None => HashMap :: new ( ) ,
511
- } ;
512
-
446
+ // Parse pulse (specific to handlers)
513
447
let pulse = config
514
448
. get_data_by_key ( "pulse" )
515
449
. map ( |v| v. as_int ( ) . map_err ( |_| "pulse must be an integer" ) )
516
450
. transpose ( ) ?
517
451
. map ( |n| n as u64 ) ;
518
452
519
- let return_options = if let Some ( return_config) = config. get_data_by_key ( "return_options" ) {
520
- let record = return_config
521
- . as_record ( )
522
- . map_err ( |_| "return must be a record" ) ?;
523
-
524
- let suffix = record
525
- . get ( "suffix" )
526
- . map ( |v| v. as_str ( ) . map_err ( |_| "suffix must be a string" ) )
527
- . transpose ( ) ?
528
- . map ( String :: from) ;
529
-
530
- let ttl = record
531
- . get ( "ttl" )
532
- . map ( |v| serde_json:: from_str ( & value_to_json ( v) . to_string ( ) ) )
533
- . transpose ( )
534
- . map_err ( |e| format ! ( "invalid TTL: {}" , e) ) ?;
535
-
536
- Some ( ReturnOptions { suffix, ttl } )
537
- } else {
538
- None
539
- } ;
540
-
541
453
engine. state . merge_env ( & mut stack) ?;
542
454
543
455
Ok ( (
544
- run,
456
+ common_options . run ,
545
457
HandlerConfig {
546
458
resume_from,
547
- modules,
548
459
pulse,
549
- return_options,
460
+ return_options : common_options . return_options ,
550
461
} ,
551
462
) )
552
463
}
0 commit comments