Skip to main content

nu_utils/
utils.rs

1#[cfg(windows)]
2use crossterm_winapi::{ConsoleMode, Handle};
3use lscolors::LsColors;
4use std::io::{self, Result, Write};
5
6pub fn enable_vt_processing() -> Result<()> {
7    #[cfg(windows)]
8    {
9        let console_out_mode = ConsoleMode::from(Handle::current_out_handle()?);
10        let old_out_mode = console_out_mode.mode()?;
11        let console_in_mode = ConsoleMode::from(Handle::current_in_handle()?);
12        let old_in_mode = console_in_mode.mode()?;
13
14        enable_vt_processing_input(console_in_mode, old_in_mode)?;
15        enable_vt_processing_output(console_out_mode, old_out_mode)?;
16    }
17    Ok(())
18}
19
20#[cfg(windows)]
21fn enable_vt_processing_input(console_in_mode: ConsoleMode, mode: u32) -> Result<()> {
22    //
23    // Input Mode flags:
24    //
25    // #define ENABLE_PROCESSED_INPUT              0x0001
26    // #define ENABLE_LINE_INPUT                   0x0002
27    // #define ENABLE_ECHO_INPUT                   0x0004
28    // #define ENABLE_WINDOW_INPUT                 0x0008
29    // #define ENABLE_MOUSE_INPUT                  0x0010
30    // #define ENABLE_INSERT_MODE                  0x0020
31    // #define ENABLE_QUICK_EDIT_MODE              0x0040
32    // #define ENABLE_EXTENDED_FLAGS               0x0080
33    // #define ENABLE_AUTO_POSITION                0x0100
34    // #define ENABLE_VIRTUAL_TERMINAL_INPUT       0x0200
35
36    const ENABLE_PROCESSED_INPUT: u32 = 0x0001;
37    const ENABLE_LINE_INPUT: u32 = 0x0002;
38    const ENABLE_ECHO_INPUT: u32 = 0x0004;
39    const ENABLE_VIRTUAL_TERMINAL_INPUT: u32 = 0x0200;
40
41    console_in_mode.set_mode(
42        mode | ENABLE_VIRTUAL_TERMINAL_INPUT
43            & ENABLE_ECHO_INPUT
44            & ENABLE_LINE_INPUT
45            & ENABLE_PROCESSED_INPUT,
46    )
47}
48
49#[cfg(windows)]
50fn enable_vt_processing_output(console_out_mode: ConsoleMode, mode: u32) -> Result<()> {
51    //
52    // Output Mode flags:
53    //
54    // #define ENABLE_PROCESSED_OUTPUT             0x0001
55    // #define ENABLE_WRAP_AT_EOL_OUTPUT           0x0002
56    // #define ENABLE_VIRTUAL_TERMINAL_PROCESSING  0x0004
57    // #define DISABLE_NEWLINE_AUTO_RETURN         0x0008
58    // #define ENABLE_LVB_GRID_WORLDWIDE           0x0010
59
60    pub const ENABLE_PROCESSED_OUTPUT: u32 = 0x0001;
61    pub const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x0004;
62
63    console_out_mode.set_mode(mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
64}
65
66pub fn stdout_write_all_and_flush<T>(output: T) -> Result<()>
67where
68    T: AsRef<[u8]>,
69{
70    let stdout = std::io::stdout();
71    stdout.lock().write_all(output.as_ref())?;
72    stdout.lock().flush()
73}
74
75pub fn stderr_write_all_and_flush<T>(output: T) -> Result<()>
76where
77    T: AsRef<[u8]>,
78{
79    let stderr = std::io::stderr();
80
81    match stderr.lock().write_all(output.as_ref()) {
82        Ok(_) => Ok(stderr.lock().flush()?),
83        Err(err) => Err(err),
84    }
85}
86
87pub fn get_ls_colors(lscolors_env_string: Option<String>) -> LsColors {
88    if let Some(s) = lscolors_env_string {
89        LsColors::from_string(&s)
90    } else {
91        LsColors::from_string(
92            &[
93                "st=0",
94                "di=0;38;5;81",
95                "so=0;38;5;16;48;5;203",
96                "ln=0;38;5;203",
97                "cd=0;38;5;203;48;5;236",
98                "ex=1;38;5;203",
99                "or=0;38;5;16;48;5;203",
100                "fi=0",
101                "bd=0;38;5;81;48;5;236",
102                "ow=0",
103                "mi=0;38;5;16;48;5;203",
104                "*~=0;38;5;243",
105                "no=0",
106                "tw=0",
107                "pi=0;38;5;16;48;5;81",
108                "*.z=4;38;5;203",
109                "*.t=0;38;5;48",
110                "*.o=0;38;5;243",
111                "*.d=0;38;5;48",
112                "*.a=1;38;5;203",
113                "*.c=0;38;5;48",
114                "*.m=0;38;5;48",
115                "*.p=0;38;5;48",
116                "*.r=0;38;5;48",
117                "*.h=0;38;5;48",
118                "*.ml=0;38;5;48",
119                "*.ll=0;38;5;48",
120                "*.gv=0;38;5;48",
121                "*.cp=0;38;5;48",
122                "*.xz=4;38;5;203",
123                "*.hs=0;38;5;48",
124                "*css=0;38;5;48",
125                "*.ui=0;38;5;149",
126                "*.pl=0;38;5;48",
127                "*.ts=0;38;5;48",
128                "*.gz=4;38;5;203",
129                "*.so=1;38;5;203",
130                "*.cr=0;38;5;48",
131                "*.fs=0;38;5;48",
132                "*.bz=4;38;5;203",
133                "*.ko=1;38;5;203",
134                "*.as=0;38;5;48",
135                "*.sh=0;38;5;48",
136                "*.pp=0;38;5;48",
137                "*.el=0;38;5;48",
138                "*.py=0;38;5;48",
139                "*.lo=0;38;5;243",
140                "*.bc=0;38;5;243",
141                "*.cc=0;38;5;48",
142                "*.pm=0;38;5;48",
143                "*.rs=0;38;5;48",
144                "*.di=0;38;5;48",
145                "*.jl=0;38;5;48",
146                "*.rb=0;38;5;48",
147                "*.md=0;38;5;185",
148                "*.js=0;38;5;48",
149                "*.cjs=0;38;5;48",
150                "*.mjs=0;38;5;48",
151                "*.go=0;38;5;48",
152                "*.vb=0;38;5;48",
153                "*.hi=0;38;5;243",
154                "*.kt=0;38;5;48",
155                "*.hh=0;38;5;48",
156                "*.cs=0;38;5;48",
157                "*.mn=0;38;5;48",
158                "*.nb=0;38;5;48",
159                "*.7z=4;38;5;203",
160                "*.ex=0;38;5;48",
161                "*.rm=0;38;5;208",
162                "*.ps=0;38;5;186",
163                "*.td=0;38;5;48",
164                "*.la=0;38;5;243",
165                "*.aux=0;38;5;243",
166                "*.xmp=0;38;5;149",
167                "*.mp4=0;38;5;208",
168                "*.rpm=4;38;5;203",
169                "*.m4a=0;38;5;208",
170                "*.zip=4;38;5;203",
171                "*.dll=1;38;5;203",
172                "*.bcf=0;38;5;243",
173                "*.awk=0;38;5;48",
174                "*.aif=0;38;5;208",
175                "*.zst=4;38;5;203",
176                "*.bak=0;38;5;243",
177                "*.tgz=4;38;5;203",
178                "*.com=1;38;5;203",
179                "*.clj=0;38;5;48",
180                "*.sxw=0;38;5;186",
181                "*.vob=0;38;5;208",
182                "*.fsx=0;38;5;48",
183                "*.doc=0;38;5;186",
184                "*.mkv=0;38;5;208",
185                "*.tbz=4;38;5;203",
186                "*.ogg=0;38;5;208",
187                "*.wma=0;38;5;208",
188                "*.mid=0;38;5;208",
189                "*.kex=0;38;5;186",
190                "*.out=0;38;5;243",
191                "*.ltx=0;38;5;48",
192                "*.sql=0;38;5;48",
193                "*.ppt=0;38;5;186",
194                "*.tex=0;38;5;48",
195                "*.odp=0;38;5;186",
196                "*.log=0;38;5;243",
197                "*.arj=4;38;5;203",
198                "*.ipp=0;38;5;48",
199                "*.sbt=0;38;5;48",
200                "*.jpg=0;38;5;208",
201                "*.yml=0;38;5;149",
202                "*.txt=0;38;5;185",
203                "*.csv=0;38;5;185",
204                "*.dox=0;38;5;149",
205                "*.pro=0;38;5;149",
206                "*.bst=0;38;5;149",
207                "*TODO=1",
208                "*.mir=0;38;5;48",
209                "*.bat=1;38;5;203",
210                "*.m4v=0;38;5;208",
211                "*.pod=0;38;5;48",
212                "*.cfg=0;38;5;149",
213                "*.pas=0;38;5;48",
214                "*.tml=0;38;5;149",
215                "*.bib=0;38;5;149",
216                "*.ini=0;38;5;149",
217                "*.apk=4;38;5;203",
218                "*.h++=0;38;5;48",
219                "*.pyc=0;38;5;243",
220                "*.img=4;38;5;203",
221                "*.rst=0;38;5;185",
222                "*.swf=0;38;5;208",
223                "*.htm=0;38;5;185",
224                "*.ttf=0;38;5;208",
225                "*.elm=0;38;5;48",
226                "*hgrc=0;38;5;149",
227                "*.bmp=0;38;5;208",
228                "*.fsi=0;38;5;48",
229                "*.pgm=0;38;5;208",
230                "*.dpr=0;38;5;48",
231                "*.xls=0;38;5;186",
232                "*.tcl=0;38;5;48",
233                "*.mli=0;38;5;48",
234                "*.ppm=0;38;5;208",
235                "*.bbl=0;38;5;243",
236                "*.lua=0;38;5;48",
237                "*.asa=0;38;5;48",
238                "*.pbm=0;38;5;208",
239                "*.avi=0;38;5;208",
240                "*.def=0;38;5;48",
241                "*.mov=0;38;5;208",
242                "*.hxx=0;38;5;48",
243                "*.tif=0;38;5;208",
244                "*.fon=0;38;5;208",
245                "*.zsh=0;38;5;48",
246                "*.png=0;38;5;208",
247                "*.inc=0;38;5;48",
248                "*.jar=4;38;5;203",
249                "*.swp=0;38;5;243",
250                "*.pid=0;38;5;243",
251                "*.gif=0;38;5;208",
252                "*.ind=0;38;5;243",
253                "*.erl=0;38;5;48",
254                "*.ilg=0;38;5;243",
255                "*.eps=0;38;5;208",
256                "*.tsx=0;38;5;48",
257                "*.git=0;38;5;243",
258                "*.inl=0;38;5;48",
259                "*.rtf=0;38;5;186",
260                "*.hpp=0;38;5;48",
261                "*.kts=0;38;5;48",
262                "*.deb=4;38;5;203",
263                "*.svg=0;38;5;208",
264                "*.pps=0;38;5;186",
265                "*.ps1=0;38;5;48",
266                "*.c++=0;38;5;48",
267                "*.cpp=0;38;5;48",
268                "*.bsh=0;38;5;48",
269                "*.php=0;38;5;48",
270                "*.exs=0;38;5;48",
271                "*.toc=0;38;5;243",
272                "*.mp3=0;38;5;208",
273                "*.epp=0;38;5;48",
274                "*.rar=4;38;5;203",
275                "*.wav=0;38;5;208",
276                "*.xlr=0;38;5;186",
277                "*.tmp=0;38;5;243",
278                "*.cxx=0;38;5;48",
279                "*.iso=4;38;5;203",
280                "*.dmg=4;38;5;203",
281                "*.gvy=0;38;5;48",
282                "*.bin=4;38;5;203",
283                "*.wmv=0;38;5;208",
284                "*.blg=0;38;5;243",
285                "*.ods=0;38;5;186",
286                "*.psd=0;38;5;208",
287                "*.mpg=0;38;5;208",
288                "*.dot=0;38;5;48",
289                "*.cgi=0;38;5;48",
290                "*.xml=0;38;5;185",
291                "*.htc=0;38;5;48",
292                "*.ics=0;38;5;186",
293                "*.bz2=4;38;5;203",
294                "*.tar=4;38;5;203",
295                "*.csx=0;38;5;48",
296                "*.ico=0;38;5;208",
297                "*.sxi=0;38;5;186",
298                "*.nix=0;38;5;149",
299                "*.pkg=4;38;5;203",
300                "*.bag=4;38;5;203",
301                "*.fnt=0;38;5;208",
302                "*.idx=0;38;5;243",
303                "*.xcf=0;38;5;208",
304                "*.exe=1;38;5;203",
305                "*.flv=0;38;5;208",
306                "*.fls=0;38;5;243",
307                "*.otf=0;38;5;208",
308                "*.vcd=4;38;5;203",
309                "*.vim=0;38;5;48",
310                "*.sty=0;38;5;243",
311                "*.pdf=0;38;5;186",
312                "*.odt=0;38;5;186",
313                "*.purs=0;38;5;48",
314                "*.h264=0;38;5;208",
315                "*.jpeg=0;38;5;208",
316                "*.dart=0;38;5;48",
317                "*.pptx=0;38;5;186",
318                "*.lock=0;38;5;243",
319                "*.bash=0;38;5;48",
320                "*.rlib=0;38;5;243",
321                "*.hgrc=0;38;5;149",
322                "*.psm1=0;38;5;48",
323                "*.toml=0;38;5;149",
324                "*.tbz2=4;38;5;203",
325                "*.yaml=0;38;5;149",
326                "*.make=0;38;5;149",
327                "*.orig=0;38;5;243",
328                "*.html=0;38;5;185",
329                "*.fish=0;38;5;48",
330                "*.diff=0;38;5;48",
331                "*.xlsx=0;38;5;186",
332                "*.docx=0;38;5;186",
333                "*.json=0;38;5;149",
334                "*.psd1=0;38;5;48",
335                "*.tiff=0;38;5;208",
336                "*.flac=0;38;5;208",
337                "*.java=0;38;5;48",
338                "*.less=0;38;5;48",
339                "*.mpeg=0;38;5;208",
340                "*.conf=0;38;5;149",
341                "*.lisp=0;38;5;48",
342                "*.epub=0;38;5;186",
343                "*.cabal=0;38;5;48",
344                "*.patch=0;38;5;48",
345                "*.shtml=0;38;5;185",
346                "*.class=0;38;5;243",
347                "*.xhtml=0;38;5;185",
348                "*.mdown=0;38;5;185",
349                "*.dyn_o=0;38;5;243",
350                "*.cache=0;38;5;243",
351                "*.swift=0;38;5;48",
352                "*README=0;38;5;16;48;5;186",
353                "*passwd=0;38;5;149",
354                "*.ipynb=0;38;5;48",
355                "*shadow=0;38;5;149",
356                "*.toast=4;38;5;203",
357                "*.cmake=0;38;5;149",
358                "*.scala=0;38;5;48",
359                "*.dyn_hi=0;38;5;243",
360                "*.matlab=0;38;5;48",
361                "*.config=0;38;5;149",
362                "*.gradle=0;38;5;48",
363                "*.groovy=0;38;5;48",
364                "*.ignore=0;38;5;149",
365                "*LICENSE=0;38;5;249",
366                "*TODO.md=1",
367                "*COPYING=0;38;5;249",
368                "*.flake8=0;38;5;149",
369                "*INSTALL=0;38;5;16;48;5;186",
370                "*setup.py=0;38;5;149",
371                "*.gemspec=0;38;5;149",
372                "*.desktop=0;38;5;149",
373                "*Makefile=0;38;5;149",
374                "*Doxyfile=0;38;5;149",
375                "*TODO.txt=1",
376                "*README.md=0;38;5;16;48;5;186",
377                "*.kdevelop=0;38;5;149",
378                "*.rgignore=0;38;5;149",
379                "*configure=0;38;5;149",
380                "*.DS_Store=0;38;5;243",
381                "*.fdignore=0;38;5;149",
382                "*COPYRIGHT=0;38;5;249",
383                "*.markdown=0;38;5;185",
384                "*.cmake.in=0;38;5;149",
385                "*.gitconfig=0;38;5;149",
386                "*INSTALL.md=0;38;5;16;48;5;186",
387                "*CODEOWNERS=0;38;5;149",
388                "*.gitignore=0;38;5;149",
389                "*Dockerfile=0;38;5;149",
390                "*SConstruct=0;38;5;149",
391                "*.scons_opt=0;38;5;243",
392                "*README.txt=0;38;5;16;48;5;186",
393                "*SConscript=0;38;5;149",
394                "*.localized=0;38;5;243",
395                "*.travis.yml=0;38;5;186",
396                "*Makefile.in=0;38;5;243",
397                "*.gitmodules=0;38;5;149",
398                "*LICENSE-MIT=0;38;5;249",
399                "*Makefile.am=0;38;5;149",
400                "*INSTALL.txt=0;38;5;16;48;5;186",
401                "*MANIFEST.in=0;38;5;149",
402                "*.synctex.gz=0;38;5;243",
403                "*.fdb_latexmk=0;38;5;243",
404                "*CONTRIBUTORS=0;38;5;16;48;5;186",
405                "*configure.ac=0;38;5;149",
406                "*.applescript=0;38;5;48",
407                "*appveyor.yml=0;38;5;186",
408                "*.clang-format=0;38;5;149",
409                "*.gitattributes=0;38;5;149",
410                "*LICENSE-APACHE=0;38;5;249",
411                "*CMakeCache.txt=0;38;5;243",
412                "*CMakeLists.txt=0;38;5;149",
413                "*CONTRIBUTORS.md=0;38;5;16;48;5;186",
414                "*requirements.txt=0;38;5;149",
415                "*CONTRIBUTORS.txt=0;38;5;16;48;5;186",
416                "*.sconsign.dblite=0;38;5;243",
417                "*package-lock.json=0;38;5;243",
418                "*.CFUserTextEncoding=0;38;5;243",
419                "*.fb2=0;38;5;186",
420            ]
421            .join(":"),
422        )
423    }
424}
425
426// Log some performance metrics (green text with yellow timings).
427// Uses a custom target "nu::perf::<module_path>" so that --log-level perf
428// can filter these logs via the simplelog target filter.
429#[macro_export]
430macro_rules! perf {
431    ($msg:expr, $dur:expr, $use_color:expr) => {{
432        let target = concat!("nu::perf::", module_path!());
433        if $use_color {
434            log::info!(
435                target: target,
436                "perf: {}:{}:{} \x1b[32m{}\x1b[0m took \x1b[33m{:?}\x1b[0m",
437                file!(),
438                line!(),
439                column!(),
440                $msg,
441                $dur.elapsed(),
442            );
443        } else {
444            log::info!(
445                target: target,
446                "perf: {}:{}:{} {} took {:?}",
447                file!(),
448                line!(),
449                column!(),
450                $msg,
451                $dur.elapsed(),
452            );
453        }
454    }};
455}
456
457/// Returns the terminal size (columns, rows).
458///
459/// This utility variant allows getting a fallback value when compiling for wasm32 without having
460/// to rearrange other bits of the codebase.
461///
462/// See [`crossterm::terminal::size`].
463pub fn terminal_size() -> io::Result<(u16, u16)> {
464    #[cfg(feature = "os")]
465    return crossterm::terminal::size();
466
467    #[cfg(not(feature = "os"))]
468    return Err(io::Error::from(io::ErrorKind::Unsupported));
469}