Shells in OCaml
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

Compound Commands: Cases

This adds initial functionality for the case compound command.

+87 -9
+42 -7
src/lib/eval.ml
··· 453 453 | Some s when kind = `Smallest -> (so_far, Some s) 454 454 | _ -> ( 455 455 let s = so_far ^ String.make 1 c in 456 - match Glob.test ~pattern [ s ] with 456 + match Glob.tests ~pattern [ s ] with 457 457 | [ s ] -> (s, Some s) 458 458 | _ -> (s, acc))) 459 459 ("", None) param ··· 468 468 | Some s when kind = `Smallest -> (so_far, Some s) 469 469 | _ -> ( 470 470 let s = String.make 1 c ^ so_far in 471 - match Glob.test ~pattern [ s ] with 471 + match Glob.tests ~pattern [ s ] with 472 472 | [ s ] -> (s, Some s) 473 473 | _ -> (s, acc))) 474 474 ("", None) ··· 711 711 | Exit.Zero ctx -> exec ctx (e2, Some sep2) 712 712 | Exit.Nonzero { value = ctx; _ } -> handle_else_part ctx else_part) 713 713 714 + and handle_case_clause ctx = function 715 + | Ast.Case _ -> Exit.zero ctx 716 + | Cases (word, case_list) -> ( 717 + let ctx, word = expand_cst ctx word in 718 + let scrutinee = Ast.word_components_to_string word in 719 + let res = 720 + Nlist.fold_left 721 + (fun acc pat -> 722 + match acc with 723 + | Some _ as ctx -> ctx 724 + | None -> ( 725 + match pat with 726 + | Ast.Case_pattern _ -> assert false 727 + | Ast.Case_compound (p, sub) -> 728 + Nlist.fold_left 729 + (fun inner_acc pattern -> 730 + match inner_acc with 731 + | Some _ as v -> v 732 + | None -> 733 + let ctx, pattern = expand_cst ctx pattern in 734 + let pattern = 735 + Ast.word_components_to_string pattern 736 + in 737 + if Glob.test ~pattern scrutinee then begin 738 + Some (exec_subshell ctx sub) 739 + end 740 + else inner_acc) 741 + None p)) 742 + None case_list 743 + in 744 + match res with Some ctx -> ctx | None -> Exit.zero ctx) 745 + 746 + and exec_subshell ctx (term, sep) = 747 + let saved_ctx = ctx in 748 + let e = exec ctx (term, Some sep) in 749 + let v = e >|= fun _ -> saved_ctx in 750 + v 751 + 714 752 and handle_compound_command ctx v : ctx Exit.t = 715 753 match v with 716 754 | Ast.ForClause fc -> handle_for_clause ctx fc 717 755 | Ast.IfClause if_ -> handle_if_clause ctx if_ 718 756 | Ast.BraceGroup (term, sep) -> exec ctx (term, Some sep) 719 - | Ast.Subshell (term, sep) -> 720 - let saved_ctx = ctx in 721 - let e = exec ctx (term, Some sep) in 722 - let v = e >|= fun _ -> saved_ctx in 723 - v 757 + | Ast.Subshell s -> exec_subshell ctx s 758 + | Ast.CaseClause cases -> handle_case_clause ctx cases 724 759 | _ as c -> 725 760 Fmt.epr "Compound command not supported: %a\n%!" yojson_pp 726 761 (Ast.compound_command_to_yojson c);
+6 -2
src/lib/import.ml
··· 75 75 end 76 76 77 77 module Glob = struct 78 - let test ~pattern s = List.filter Glob.(test (of_string pattern)) s 79 - let glob_dir ~pattern dir = test ~pattern (Eio.Path.read_dir dir) 78 + let tests ~pattern s = List.filter Glob.(test (of_string pattern)) s 79 + 80 + let test ~pattern s = 81 + match tests ~pattern [ s ] with [ _ ] -> true | _ :: _ | [] -> false 82 + 83 + let glob_dir ~pattern dir = tests ~pattern (Eio.Path.read_dir dir) 80 84 end
+39
test/cases.t
··· 1 + Case compound command 2 + 3 + $ cat > test.sh << EOF 4 + > 5 + > service () { 6 + > case "\$1" in 7 + > start|begin) 8 + > echo "Starting up service..." 9 + > ;; 10 + > status) 11 + > echo "All good..." 12 + > ;; 13 + > stop) 14 + > echo "Stopping service" 15 + > ;; 16 + > *) 17 + > echo "Unknown command: \$1" 18 + > ;; 19 + > esac 20 + > } 21 + > 22 + > service start 23 + > service status 24 + > service stop 25 + > service foo 26 + > 27 + > EOF 28 + 29 + $ sh test.sh 30 + Starting up service... 31 + All good... 32 + Stopping service 33 + Unknown command: foo 34 + 35 + $ msh test.sh 36 + Starting up service... 37 + All good... 38 + Stopping service 39 + Unknown command: foo