1
- use anyhow:: Context as _;
1
+ use anyhow:: { bail , Context as _} ;
2
2
use colored:: Colorize as _;
3
3
use structopt:: clap:: AppSettings ;
4
4
@@ -35,6 +35,51 @@ impl FromStr for OutputMode {
35
35
}
36
36
}
37
37
38
+ // this could have fewer nested if’s, but this produces better error messages
39
+ fn parse_newline_on ( s : & str ) -> Result < char , anyhow:: Error > {
40
+ if let Ok ( c) = s. parse :: < char > ( ) {
41
+ Ok ( c)
42
+
43
+ // if it starts with 0x then parse the hex byte
44
+ } else if & s[ 0 ..2 ] == "0x" {
45
+ if s. len ( ) == 4 {
46
+ if let Ok ( n) = u8:: from_str_radix ( & s[ 2 ..4 ] , 16 ) {
47
+ Ok ( n as char )
48
+ } else {
49
+ bail ! ( "invalid hex byte" )
50
+ }
51
+ } else {
52
+ bail ! ( "hex byte must have 2 characters" )
53
+ }
54
+ // if it starts with 0b then parse the binary byte
55
+ } else if & s[ 0 ..2 ] == "0b" {
56
+ if s. len ( ) == 10 {
57
+ if let Ok ( n) = u8:: from_str_radix ( & s[ 2 ..10 ] , 2 ) {
58
+ Ok ( n as char )
59
+ } else {
60
+ bail ! ( "invalid binary byte" )
61
+ }
62
+ } else {
63
+ bail ! ( "binary byte must have 8 characters" )
64
+ }
65
+ } else {
66
+ bail ! ( "must be a single character or a byte in hex or binary notation" )
67
+ }
68
+ }
69
+
70
+ #[ test]
71
+ fn test_parse_newline_on ( ) {
72
+ assert_eq ! ( parse_newline_on( "a" ) . unwrap( ) , 'a' ) ;
73
+ assert_eq ! ( parse_newline_on( "\n " ) . unwrap( ) , '\n' ) ;
74
+ assert_eq ! ( parse_newline_on( "0x41" ) . unwrap( ) , 'A' ) ;
75
+ assert_eq ! ( parse_newline_on( "0b01000001" ) . unwrap( ) , 'A' ) ;
76
+ assert ! ( parse_newline_on( "not a char" ) . is_err( ) ) ;
77
+ assert ! ( parse_newline_on( "0x" ) . is_err( ) ) ;
78
+ assert ! ( parse_newline_on( "0xzz" ) . is_err( ) ) ;
79
+ assert ! ( parse_newline_on( "0b" ) . is_err( ) ) ;
80
+ assert ! ( parse_newline_on( "0b0a0a0a0a" ) . is_err( ) ) ;
81
+ }
82
+
38
83
/// ravedude is a rust wrapper around avrdude for providing the smoothest possible development
39
84
/// experience with rust on AVR microcontrollers.
40
85
///
@@ -74,6 +119,27 @@ struct Args {
74
119
#[ structopt( long = "debug-avrdude" ) ]
75
120
debug_avrdude : bool ,
76
121
122
+ /// Output mode.
123
+ ///
124
+ /// Can be ascii, hex, dec or bin
125
+ #[ structopt( short = "o" ) ]
126
+ output_mode : Option < OutputMode > ,
127
+
128
+ /// Print a newline after this byte
129
+ /// not used with output_mode ascii
130
+ /// hex (0x) and bin (0b) notations are supported.
131
+ /// matching chars/bytes are NOT removed
132
+ /// to add newlines after \n (in non-ascii mode), use \n, 0x0a or 0b00001010
133
+ #[ structopt( long = "newline-on" , parse( try_from_str = parse_newline_on) ) ]
134
+ newline_on : Option < char > ,
135
+
136
+ /// Print a newline after n bytes
137
+ /// not used with output_mode ascii
138
+ /// defaults to 16 for hex and dec and 8 for bin
139
+ /// if dividable by 4, bytes will be grouped to 4
140
+ #[ structopt( long = "newline-after" ) ]
141
+ newline_after : Option < u8 > ,
142
+
77
143
/// Which board to interact with.
78
144
///
79
145
/// Must be one of the known board identifiers:
@@ -101,12 +167,6 @@ struct Args {
101
167
/// If no binary is given, flashing will be skipped.
102
168
#[ structopt( name = "BINARY" , parse( from_os_str) ) ]
103
169
bin : Option < std:: path:: PathBuf > ,
104
-
105
- /// Output mode.
106
- ///
107
- /// Can be ascii, hex, dec or bin
108
- #[ structopt( short = "o" ) ]
109
- output_mode : Option < OutputMode > ,
110
170
}
111
171
112
172
fn main ( ) {
@@ -125,6 +185,10 @@ fn ravedude() -> anyhow::Result<()> {
125
185
126
186
let board = board:: get_board ( & args. board ) . expect ( "board not found" ) ;
127
187
188
+ if args. newline_on . is_some ( ) && args. newline_after . is_some ( ) {
189
+ bail ! ( "newline_on and newline_after cannot be used at the same time" ) ;
190
+ }
191
+
128
192
task_message ! ( "Board" , "{}" , board. display_name( ) ) ;
129
193
130
194
if let Some ( wait_time) = args. reset_delay {
0 commit comments