char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
688e96e
main
1use std:: path::{ Path , PathBuf }; 2 3use crate :: cli:: ParseError ; 4use crate :: fragments::{ Arg , Entry , Parser , flag_value, reject}; 5use avril_runtime:: caps:: PathTarget ; 6 7fn single < E >( 8parser : & mut Parser , 9bare : & [ & str ], 10own : & mut impl FnMut ( & str , & Path ) ->Result < bool , E >, 11) ->Result < Option < String >, E > 12where 13E : From < ParseError >, 14{ 15let mut raw =None ; 16while let Some ( arg) = parser. next () ?{ 17match arg{ 18Arg :: Positional ( arg) =>{ 19if raw. replace ( arg). is_some () { 20return Err ( 21ParseError :: Usage ( "Expected exactly one entry module" . into ()). into (), 22); 23} 24} 25Arg :: Flag ( arg) if own ( & arg, & parser. cwd ) ? =>{} 26Arg :: Flag ( arg) =>return Err ( reject ( & arg, bare). into ()), 27} 28} 29Ok ( raw) 30} 31 32pub ( crate ) fn parse_entry < E >( 33name : & str , 34argv : Vec < String >, 35cwd : PathBuf , 36bare : & [ & str ], 37own : impl FnMut ( & str , & Path ) ->Result < bool , E >, 38) ->Result < Entry , E > 39where 40E : From < ParseError >, 41{ 42let mut parser =Parser :: new ( name, argv, & cwd) ?; 43let mut own = own; 44let raw =single ( & mut parser, bare, & mut own) ?; 45let raw = raw. ok_or_else ( || parser. usage ()) ?; 46Ok ( parser. entry ( & raw) ?) 47} 48 49pub struct EntryArgs { 50pub entry : Entry , 51pub script : Vec < String >, 52} 53 54# [ derive ( Debug , thiserror :: Error )] 55pub enum ReplParseError { 56# [ error ( transparent )] 57Generic ( # [ from ] ParseError ), 58# [ error ( "The REPL does not accept a module; run one with `avril run <module>`" )] 59UnexpectedModule , 60} 61 62impl EntryArgs { 63pub fn parse_repl ( 64argv : Vec < String >, 65script : Vec < String >, 66cwd : PathBuf , 67) ->Result < Self , ReplParseError > { 68let mut parser =Parser :: new ( "repl" , argv, & cwd) ?; 69if single ::< ReplParseError >( & mut parser, & [], & mut |_, _|Ok ( false )) ?. is_some () { 70return Err ( ReplParseError :: UnexpectedModule ); 71} 72let entry = parser. synthetic ( ".avril-repl.js" ) ?; 73Ok ( Self { entry, script}) 74} 75 76pub fn parse_run ( 77argv : Vec < String >, 78script : Vec < String >, 79cwd : PathBuf , 80) ->Result < Self , ParseError > { 81let entry =parse_entry ::< ParseError >( "run" , argv, cwd, & [], |_, _|Ok ( false )) ?; 82Ok ( Self { entry, script}) 83} 84} 85 86pub struct ServeArgs { 87pub common : EntryArgs , 88pub listener : avril_http:: Address , 89} 90 91# [ derive ( Debug , thiserror :: Error )] 92pub enum ServeParseError { 93# [ error ( transparent )] 94Generic ( # [ from ] ParseError ), 95# [ error ( "Invalid HTTP listen port" )] 96BadPort , 97# [ error ( "--unix cannot be combined with --hostname or --port" )] 98UnixConflict , 99# [ error ( "Unix socket paths must be UTF-8" )] 100SocketUtf8 , 101} 102 103impl ServeArgs { 104pub fn parse ( 105argv : Vec < String >, 106script : Vec < String >, 107cwd : PathBuf , 108) ->Result < Self , ServeParseError > { 109let mut hostname =None ; 110let mut port =None ; 111let mut socket =None ; 112let entry =parse_entry ::< ServeParseError >( "serve" , argv, cwd, & [], |arg, cwd|{ 113let ( flag, value) =flag_value ( arg) ?; 114match flag{ 115"--hostname" => hostname =Some ( value. to_owned ()), 116"--port" =>{ 117 port =Some ( value. parse ::< u16 >(). map_err ( |_|ServeParseError :: BadPort ) ?) 118} 119"--unix" => socket =Some ( cwd. join ( value)), 120 _ =>return Ok ( false ), 121} 122Ok ( true ) 123}) ?; 124let listener =match socket{ 125Some ( socket) if hostname. is_none () && port. is_none () =>{ 126let target =PathTarget :: for_entry ( socket). map_err ( ParseError :: Io ) ?; 127 avril_http:: Address :: Unix { 128path : Some ( 129 target 130. as_path () 131. to_str () 132. ok_or ( ServeParseError :: SocketUtf8 ) ? 133. to_owned (), 134), 135} 136} 137Some ( _) =>return Err ( ServeParseError :: UnixConflict ), 138None => avril_http:: Address :: Tcp { 139hostname : hostname. unwrap_or_else ( ||"127.0.0.1" . into ()), 140port : port. unwrap_or ( 8000 ), 141}, 142}; 143Ok ( Self { 144common : EntryArgs { entry, script}, 145 listener, 146}) 147} 148} 149 150pub ( crate ) fn parse_cache ( argv : Vec < String >, cwd : PathBuf ) ->Result < Entry , ParseError > { 151parse_entry ::< ParseError >( "cache" , argv, cwd, & [], |_, _|Ok ( false )) 152} 153 154pub ( crate ) fn parse_info ( argv : Vec < String >, cwd : PathBuf ) ->Result < Entry , ParseError > { 155parse_entry ::< ParseError >( "info" , argv, cwd, & [], |_, _|Ok ( false )) 156} 157 158pub struct UpdateArgs { 159pub entry : Entry , 160pub prune : bool , 161} 162 163impl UpdateArgs { 164pub fn parse ( argv : Vec < String >, cwd : PathBuf ) ->Result < Self , ParseError > { 165let mut prune =false ; 166let mut entry =parse_entry ::< ParseError >( "update" , argv, cwd, & [ "--prune" ], |arg, _|{ 167if arg =="--prune" { 168 prune =true ; 169return Ok ( true ); 170} 171Ok ( false ) 172}) ?; 173 entry. packages . update =true ; 174Ok ( Self { entry, prune}) 175} 176} 177 178pub struct VendorArgs { 179pub entry : Entry , 180pub output : Option < PathBuf >, 181} 182 183impl VendorArgs { 184pub fn parse ( argv : Vec < String >, cwd : PathBuf ) ->Result < Self , ParseError > { 185let mut out =None ; 186let entry =parse_entry ::< ParseError >( "vendor" , argv, cwd, & [], |arg, cwd|{ 187let ( flag, value) =flag_value ( arg) ?; 188if flag !="--out" { 189return Ok ( false ); 190} 191 out =Some ( cwd. join ( value)); 192Ok ( true ) 193}) ?; 194Ok ( Self { entry, output : out}) 195} 196}