nu_utils/
utils.rs

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