@@ -73,48 +73,104 @@ static const int32_t ascii2keycode_map[128] = {
7373 KEY_X ,KEY_Y ,KEY_Z ,KEY_LEFTBRACE |FLAG_UPPERCASE ,KEY_BACKSLASH |FLAG_UPPERCASE ,KEY_RIGHTBRACE |FLAG_UPPERCASE ,KEY_GRAVE |FLAG_UPPERCASE ,-1
7474};
7575
76+ static int opt_key_delay_ms = 20 ;
77+ static int opt_key_hold_ms = 20 ;
78+ static int opt_next_delay_ms = 0 ;
79+
7680static void show_help () {
7781 puts (
7882 "Usage: type [OPTION]... [STRINGS]...\n"
7983 "Type strings.\n"
8084 "\n"
81- "Options:\n"
82- " -d, --key-delay=N Delay N milliseconds between key events (up/down each)\n"
83- " -D, --next-delay=N Delay N milliseconds between strings\n"
84- " -H, --key-hold=N Time N milliseconds to hold each key for\n"
85+ "Options:" );
86+
87+ printf (
88+ " -d, --key-delay=N Delay N milliseconds between keys (the delay between every key down/up pair) (default: %d)\n" , opt_key_delay_ms
89+ );
90+
91+ printf (
92+ " -H, --key-hold=N Hold each key for N milliseconds (the delay between key down and up) (default: %d)\n" , opt_key_hold_ms
93+ );
94+
95+ printf (
96+ " -D, --next-delay=N Delay N milliseconds between command line strings (default: %d)\n" , opt_next_delay_ms
97+ );
98+
99+ puts (
85100 " -f, --file=PATH Specify a file, the contents of which will be be typed as if passed as an argument.\n"
86101 " The filepath may also be '-' to read from stdin\n"
102+ " -e, --escape=BOOL Escape enable (1) or disable (0)\n"
87103 " -h, --help Display this help and exit\n"
88104 "\n"
105+ "Escape is enabled by default when typing command line arguments, and disabled by default when typing from file and stdin."
89106 );
90107}
91108
92- static int key_delay = 12 ;
93- static int key_hold = 0 ;
109+
94110
95111static void type_char (char c , bool delay ) {
96- int kdef = ascii2keycode_map [c ];
97- if (kdef == -1 ) {
98- return ;
99- }
112+ int kdef = ascii2keycode_map [c ];
113+ if (kdef == -1 ) {
114+ return ;
115+ }
100116
101- uint16_t kc = kdef & 0xffff ;
117+ uint16_t kc = kdef & 0xffff ;
102118
103- if (kdef & FLAG_UPPERCASE ) {
104- uinput_emit (EV_KEY , KEY_LEFTSHIFT , 1 , 1 );
105- }
106- uinput_emit (EV_KEY , kc , 1 , 1 );
119+ if (kdef & FLAG_UPPERCASE ) {
120+ uinput_emit (EV_KEY , KEY_LEFTSHIFT , 1 , 1 );
121+ }
122+ uinput_emit (EV_KEY , kc , 1 , 1 );
107123
108- usleep (key_hold * 1000 );
124+ usleep (opt_key_hold_ms * 1000 );
109125
110- uinput_emit (EV_KEY , kc , 0 , 1 );
111- if (kdef & FLAG_UPPERCASE ) {
112- uinput_emit (EV_KEY , KEY_LEFTSHIFT , 0 , 1 );
113- }
126+ uinput_emit (EV_KEY , kc , 0 , 1 );
127+ if (kdef & FLAG_UPPERCASE ) {
128+ uinput_emit (EV_KEY , KEY_LEFTSHIFT , 0 , 1 );
129+ }
114130
115- if (delay ) {
116- usleep (key_delay * 1000 );
117- }
131+ if (delay ) {
132+ usleep (opt_key_delay_ms * 1000 );
133+ }
134+ }
135+
136+ static int escape (char in ) {
137+ static int state = 0 ;
138+ static char hex_str [3 ] = {0 , 0 , 0 };
139+
140+ switch (state ) {
141+ case 0 :
142+ if (in == '\\' ) {
143+ state = 1 ;
144+ return -1 ;
145+ } else {
146+ return in ;
147+ }
148+ case 1 :
149+ state = 0 ;
150+ switch (in ) {
151+ case 'n' :
152+ return '\n' ;
153+ case 't' :
154+ return '\t' ;
155+ case 'x' :
156+ state = 2 ;
157+ return -1 ;
158+ case '\\' :
159+ return '\\' ;
160+ default :
161+ return -1 ;
162+ }
163+ case 2 :
164+ state = 3 ;
165+ hex_str [0 ] = in ;
166+ return -1 ;
167+ case 3 :
168+ state = 0 ;
169+ hex_str [1 ] = in ;
170+ return (int )strtol (hex_str , NULL , 16 );
171+ default :
172+ abort ();
173+ }
118174}
119175
120176int tool_type (int argc , char * * argv ) {
@@ -124,24 +180,27 @@ int tool_type(int argc, char **argv) {
124180 }
125181
126182
127- int next_delay_ms = 0 ;
183+
128184 const char * file_path = NULL ;
129185
186+ int enable_escape = -1 ;
187+
130188 while (1 ) {
131189 int c ;
132190
133191 static struct option long_options [] = {
134192 {"key-delay" , required_argument , 0 , 'd' },
135193 {"next-delay" , required_argument , 0 , 'D' },
136194 {"key-hold" , required_argument , 0 , 'H' },
195+ {"escape" , required_argument , 0 , 'e' },
137196 {"file" , required_argument , 0 , 'f' },
138197 {"help" , no_argument , 0 , 'h' },
139198 {0 , 0 , 0 , 0 }
140199 };
141200 /* getopt_long stores the option index here. */
142201 int option_index = 0 ;
143202
144- c = getopt_long (argc , argv , "hd:D:H:f:" ,
203+ c = getopt_long (argc , argv , "hd:D:H:f:e: " ,
145204 long_options , & option_index );
146205
147206 /* Detect the end of the options. */
@@ -159,15 +218,15 @@ int tool_type(int argc, char **argv) {
159218 printf ("\n" );
160219 break ;
161220 case 'd' :
162- key_delay = strtol (optarg , NULL , 10 );
221+ opt_key_delay_ms = strtol (optarg , NULL , 10 );
163222 break ;
164223
165224 case 'D' :
166- next_delay_ms = strtol (optarg , NULL , 10 );
225+ opt_next_delay_ms = strtol (optarg , NULL , 10 );
167226 break ;
168227
169228 case 'H' :
170- key_hold = strtol (optarg , NULL , 10 );
229+ opt_key_hold_ms = strtol (optarg , NULL , 10 );
171230 break ;
172231
173232 case 'f' :
@@ -179,6 +238,10 @@ int tool_type(int argc, char **argv) {
179238 exit (0 );
180239 break ;
181240
241+ case 'e' :
242+ enable_escape = strtol (optarg , NULL , 10 );
243+ break ;
244+
182245 case '?' :
183246 /* getopt_long already printed an error message. */
184247 break ;
@@ -189,9 +252,13 @@ int tool_type(int argc, char **argv) {
189252 }
190253
191254 if (file_path ) {
255+ if (enable_escape == -1 ) {
256+ enable_escape = 0 ;
257+ }
258+
192259 int fd = (strcmp (file_path , "-" ) == 0 )
193- ? STDIN_FILENO
194- : open (file_path , O_RDONLY );
260+ ? STDIN_FILENO
261+ : open (file_path , O_RDONLY );
195262
196263 if (fd == -1 ) {
197264 fprintf (stderr , "ydotool: type: error: failed to open %s: %s\n" , file_path ,
@@ -205,9 +272,9 @@ int tool_type(int argc, char **argv) {
205272 while ((rc = read (fd , buf , sizeof (buf )))) {
206273 if (rc > 0 ) {
207274 for (int i = 0 ; i < rc ; i ++ ) {
208- char c = buf [i ];
209- if (c ) {
210- type_char (c , i != rc - 1 );
275+ int c = enable_escape ? escape ( buf [ i ]) : buf [i ];
276+ if (c != -1 ) {
277+ type_char (( char ) c , i != rc - 1 );
211278 }
212279 }
213280 } else if (rc < 0 ) {
@@ -216,22 +283,29 @@ int tool_type(int argc, char **argv) {
216283 }
217284 }
218285 } else {
286+ if (enable_escape == -1 ) {
287+ enable_escape = 1 ;
288+ }
219289
220290 if (optind < argc ) {
221291 while (optind < argc ) {
222292 char * pstr = argv [optind ++ ];
223293
224- for (int i = 0 ;; i ++ ) {
225- char c = pstr [i ];
294+ // printf("pstr: %s\n", pstr);
295+
296+ for (int i = 0 ; ; i ++ ) {
297+ int c = enable_escape ? escape (pstr [i ]) : pstr [i ];
226298 char next = pstr [i + 1 ];
227- if (c ) {
228- type_char (c , next );
229- } else {
299+
300+ if (c == 0 ) {
230301 break ;
302+ } else if (c != -1 ) {
303+ type_char ((char )c , next );
231304 }
232305 }
233306
234- usleep (next_delay_ms * 1000 );
307+ if (argv [optind ])
308+ usleep (opt_next_delay_ms * 1000 );
235309 }
236310 } else {
237311 show_help ();
0 commit comments