diff options
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | Cargo.lock | 89 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | alacritty-completions.bash | 2 | ||||
-rw-r--r-- | alacritty-completions.fish | 3 | ||||
-rw-r--r-- | alacritty-completions.zsh | 1 | ||||
-rw-r--r-- | alacritty.man | 3 | ||||
-rw-r--r-- | alacritty.yml | 3 | ||||
-rw-r--r-- | alacritty_macos.yml | 3 | ||||
-rw-r--r-- | alacritty_windows.yml | 3 | ||||
-rw-r--r-- | build.rs | 8 | ||||
-rw-r--r-- | src/ansi.rs | 6 | ||||
-rw-r--r-- | src/cli.rs | 13 | ||||
-rw-r--r-- | src/config.rs | 87 | ||||
-rw-r--r-- | src/display.rs | 45 | ||||
-rw-r--r-- | src/event.rs | 2 | ||||
-rw-r--r-- | src/grid/tests.rs | 12 | ||||
-rw-r--r-- | src/input.rs | 4 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/logging.rs | 203 | ||||
-rw-r--r-- | src/macros.rs | 28 | ||||
-rw-r--r-- | src/main.rs | 35 | ||||
-rw-r--r-- | src/renderer/mod.rs | 14 | ||||
-rw-r--r-- | src/term/mod.rs | 14 |
24 files changed, 415 insertions, 171 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c8cbbc8..5d3f2a8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - New `mouse.url.modifiers` option to specify keyboard modifiers for opening URLs on click - Binaries for macOS, Windows and Debian-based systems are now published with GitHub releases - The keys F16-F24 have been added as options for key bindings +- Display notice about errors and warnings inside Alacritty +- Log all messages to both stderr and a log file in the system's temporary directory +- New configuration option `persistent_logging` and CLI flag `--persistent-logging`, + for keeping the log file after closing Alacritty ### Changed @@ -53,9 +53,10 @@ dependencies = [ "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "terminfo 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -73,7 +74,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rusttype 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rusttype 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -285,7 +286,7 @@ name = "cgl" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gleam 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -616,7 +617,7 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -675,7 +676,7 @@ dependencies = [ [[package]] name = "euclid" -version = "0.19.2" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -704,9 +705,9 @@ name = "failure_derive" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.20 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -742,7 +743,7 @@ dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)", "core-text 13.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "euclid 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)", + "euclid 0.19.3 (registry+https://github.com/rust-lang/crates.io-index)", "font-loader 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "freetype-rs 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -880,7 +881,7 @@ dependencies = [ [[package]] name = "gleam" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1425,9 +1426,9 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.20 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1576,7 +1577,7 @@ dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1648,7 +1649,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.23" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1669,7 +1670,7 @@ name = "quote" version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1781,7 +1782,7 @@ name = "regex-syntax" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1789,7 +1790,7 @@ name = "regex-syntax" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1814,7 +1815,7 @@ version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.27 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1857,7 +1858,7 @@ dependencies = [ [[package]] name = "rusttype" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "approx 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1951,9 +1952,9 @@ name = "serde_derive" version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.20 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2040,7 +2041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2081,7 +2082,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "static_assertions" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2099,10 +2100,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.20" +version = "0.15.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2112,9 +2113,9 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.20 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2128,6 +2129,19 @@ dependencies = [ ] [[package]] +name = "tempfile" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "termcolor" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2390,7 +2404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ucd-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2824,13 +2838,13 @@ dependencies = [ "checksum dunce 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e86b07356baf1cc7058c95807ffba0bebe0c8cadd0df4c40b292c86194eabb37" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum embed-resource 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "59edbe56442f96505f79c9116006f2e26c7f5655cccdc2c1546b2528c63bd612" -"checksum encoding_rs 0.8.10 (registry+https://github.com/rust-lang/crates.io-index)" = "065f4d0c826fdaef059ac45487169d918558e3cf86c9d89f6e81cf52369126e5" +"checksum encoding_rs 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5169856daf01399422d2cbaacdce579cd4f546c7a8481d3a4e926b313293ec56" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2a071601ed01b988f896ab14b95e67335d1eeb50190932a1320f7fe3cadc84e" "checksum errno-dragonfly 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" -"checksum euclid 0.19.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4019b11e3498dd84d8893848c3d70e40c6dc71bb277ae5252cc16af006d06872" +"checksum euclid 0.19.3 (registry+https://github.com/rust-lang/crates.io-index)" = "600657e7e5c03bfbccdc68721bc3b5abcb761553973387124eae9c9e4f02c210" "checksum expat-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" "checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" "checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" @@ -2852,7 +2866,7 @@ dependencies = [ "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" "checksum gif 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4bca55ac1f213920ce3527ccd62386f1f15fa3f1714aeee1cf93f2c416903f" "checksum gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0ffaf173cf76c73a73e080366bf556b4776ece104b06961766ff11449f38604" -"checksum gleam 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5d2f879e1548675cf46169cd7e770f6a6916f6263052fe4e6afc3b41bb7f63c" +"checksum gleam 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bef810e31d619f5b77a7daea76a26ee50e63036637048a9f2128a33d5474141a" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum glutin 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "535c6eda58adbb227604b2db10a022ffd6339d7ea3e970f338e7d98aeb24fcc3" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" @@ -2937,7 +2951,7 @@ dependencies = [ "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f54b9600d584d3b8a739e1662a595fab051329eff43f20e7d8cc22872962145b" "checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd" -"checksum proc-macro2 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)" = "88dae56b29da695d783ea7fc5a90de281f79eb38407e77f6d674dd8befc4ac47" +"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" @@ -2960,7 +2974,7 @@ dependencies = [ "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rusttype 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "11ff03da02f6d340bbee5ec55eed03ff9abd6ea013b93bc7c35973cc28f65999" -"checksum rusttype 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b8eb11f5b0a98c8eca2fb1483f42646d8c340e83e46ab416f8a063a0fd0eeb20" +"checksum rusttype 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "436c67ae0d0d24f14e1177c3ed96780ee16db82b405f0fba1bb80b46c9a30625" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" @@ -2983,16 +2997,17 @@ dependencies = [ "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" -"checksum smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "153ffa32fd170e9944f7e0838edf824a754ec4c1fc64746fcc9fe1f8fa602e5d" +"checksum smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "622df2d454c29a4d89b30dc3b27b42d7d90d6b9e587dbf8f67652eb7514da484" "checksum smithay-client-toolkit 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ef227bd9251cf8f8e54f8dd9a4b164307e515f5312cd632ebc87b56f723893a2" "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum static_assertions 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab836ee18887baf9c5312314b25a4219a37c04a59ae1b5cbc199cea093e7e433" +"checksum static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "389ce475f424f267dbed6479cbd8f126c5e1afb053b0acdaa019c74305fc65d1" "checksum stb_truetype 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "48fa7d3136d8645909de1f7c7eb5416cc43057a75ace08fc39ae736bc9da8af1" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.15.20 (registry+https://github.com/rust-lang/crates.io-index)" = "8886c8d2774e853fcd7d9d2131f6e40ba46c9c0e358e4d57178452abd6859bb0" +"checksum syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)" = "816b7af21405b011a23554ea2dc3f6576dc86ca557047c34098c1d741f10f823" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +"checksum tempfile 3.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "55c1195ef8513f3273d55ff59fe5da6940287a0d7a98331254397f464833675b" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum terminfo 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8e51065bafd2abe106b6036483b69d1741f4a1ec56ce8a2378de341637de689e" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" @@ -3016,7 +3031,7 @@ dependencies = [ "checksum tokio-udp 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "da941144b816d0dcda4db3a1ba87596e4df5e860a72b70783fe435891f80601c" "checksum tokio-uds 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df195376b43508f01570bacc73e13a1de0854dc59e79d1ec09913e8db6dd2a70" "checksum try-lock 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2aa4715743892880f70885373966c83d73ef1b0838a664ef0c76fffd35e7c2" -"checksum ucd-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0f8bfa9ff0cadcd210129ad9d2c5f145c13e9ced3d3e5d948a6213487d52444" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" @@ -49,6 +49,7 @@ image = "0.20.1" static_assertions = "0.3.0" terminfo = "0.6.1" url = "1.7.1" +time = "0.1.40" [target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd"))'.dependencies] x11-dl = "2" @@ -75,8 +76,8 @@ gl_generator = "0.10.0" [target.'cfg(windows)'.build-dependencies] embed-resource = "1.1.4" +tempfile = "3.0.4" reqwest = "0.8" -tempdir = "0.3" zip = "0.4" [profile.release] diff --git a/alacritty-completions.bash b/alacritty-completions.bash index f8ffc107..48c683e8 100644 --- a/alacritty-completions.bash +++ b/alacritty-completions.bash @@ -11,7 +11,7 @@ _alacritty() cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" prevprev="${COMP_WORDS[COMP_CWORD-2]}" - opts="-h --help -V --version --live-config-reload --no-live-config-reload --print-events -q -qq -v -vv -vvv --ref-test -e --command --config-file -d --dimensions -t --title --working-directory" + opts="-h --help -V --version --live-config-reload --no-live-config-reload --persistent-logging --print-events -q -qq -v -vv -vvv --ref-test -e --command --config-file -d --dimensions -t --title --working-directory" # If `--command` or `-e` is used, stop completing for i in "${!COMP_WORDS[@]}"; do diff --git a/alacritty-completions.fish b/alacritty-completions.fish index 516c8ea9..6ffaef4b 100644 --- a/alacritty-completions.fish +++ b/alacritty-completions.fish @@ -16,6 +16,9 @@ complete -c alacritty \ -l "no-live-config-reload" \ -d "Disable automatic config reloading" complete -c alacritty \ + -l "persistent-logging" \ + -d "Keep the log file after quitting Alacritty" +complete -c alacritty \ -f \ -l "config-file" \ -d "Specify an alternative config file" diff --git a/alacritty-completions.zsh b/alacritty-completions.zsh index d2cc0eea..be7123a1 100644 --- a/alacritty-completions.zsh +++ b/alacritty-completions.zsh @@ -9,6 +9,7 @@ _alacritty() { "(-V --version)"{-V,--version}"[Prints version information]" \ "(--no-live-config-reload)--live-config-reload[Enable automatic config reloading]" \ "(--live-config-reload)--no-live-config-reload[Disable automatic config reloading]" \ + "(--persistent-logging)--persistent-logging[Keep the log file after quitting Alacritty]" \ "--print-events[Print all events to stdout]" \ {-q,-qq}"[Reduces the level of verbosity (min is -qq)]" \ {-v,-vv,-vvv}"[Increases the level of verbosity (max is -vvv)]" \ diff --git a/alacritty.man b/alacritty.man index ba01b459..e0a1b519 100644 --- a/alacritty.man +++ b/alacritty.man @@ -19,6 +19,9 @@ Enable automatic config reloading .TP \fB\-\-no\-live\-config\-reload\fR Disable automatic config reloading +.TP +\fB\-\-persistent\-logging\fR +Keep the log file after quitting Alacritty .HP \fB\-\-print\-events\fR .TP diff --git a/alacritty.yml b/alacritty.yml index f66269a1..83ec652f 100644 --- a/alacritty.yml +++ b/alacritty.yml @@ -130,6 +130,9 @@ font: # Display the time it takes to redraw each frame. render_timer: false +# Keep the log file after quitting Alacritty. +persistent_logging: false + # If `true`, bold text is drawn using the bright color variants. draw_bold_text_with_bright_colors: true diff --git a/alacritty_macos.yml b/alacritty_macos.yml index 59f2ccb0..e4ead06d 100644 --- a/alacritty_macos.yml +++ b/alacritty_macos.yml @@ -125,6 +125,9 @@ font: # Display the time it takes to redraw each frame. render_timer: false +# Keep the log file after quitting Alacritty. +persistent_logging: false + # If `true`, bold text is drawn using the bright color variants. draw_bold_text_with_bright_colors: true diff --git a/alacritty_windows.yml b/alacritty_windows.yml index debf06ff..af429152 100644 --- a/alacritty_windows.yml +++ b/alacritty_windows.yml @@ -108,6 +108,9 @@ font: # Display the time it takes to redraw each frame. render_timer: false +# Keep the log file after quitting Alacritty. +persistent_logging: false + # Colors (Tomorrow Night Bright) colors: # Default colors @@ -14,15 +14,12 @@ #[cfg(windows)] extern crate embed_resource; #[cfg(windows)] -extern crate tempdir; +extern crate tempfile; #[cfg(windows)] extern crate reqwest; #[cfg(windows)] extern crate zip; -#[cfg(windows)] -use tempdir::TempDir; - extern crate gl_generator; use gl_generator::{Api, Fallbacks, GlobalGenerator, Profile, Registry}; @@ -66,8 +63,7 @@ fn main() { #[cfg(windows)] fn aquire_winpty_agent(out_path: &Path) { - let tmp_dir = TempDir::new("alacritty_build").unwrap(); - + let tmp_dir = tempfile::Builder::new().prefix("alacritty_build").tempdir().unwrap(); let mut response = reqwest::get(WINPTY_PACKAGE_URL).unwrap(); let mut file = OpenOptions::new() diff --git a/src/ansi.rs b/src/ansi.rs index f1ca759a..2171f868 100644 --- a/src/ansi.rs +++ b/src/ansi.rs @@ -60,7 +60,7 @@ fn parse_rgb_color(color: &[u8]) -> Option<Rgb> { let r = parse_hex!(); let val = next!(); - if val != Some('/') { println!("val={:?}", val); return None; } + if val != Some('/') { return None; } let g = parse_hex!(); if next!() != Some('/') { return None; } let b = parse_hex!(); @@ -901,7 +901,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> macro_rules! unhandled { () => {{ - warn!("[Unhandled CSI] action={:?}, args={:?}, intermediates={:?}", + debug!("[Unhandled CSI] action={:?}, args={:?}, intermediates={:?}", action, args, intermediates); return; }} @@ -1137,7 +1137,7 @@ impl<'a, H, W> vte::Perform for Performer<'a, H, W> ) { macro_rules! unhandled { () => {{ - warn!("[unhandled] esc_dispatch params={:?}, ints={:?}, byte={:?} ({:02x})", + debug!("[unhandled] esc_dispatch params={:?}, ints={:?}, byte={:?} ({:02x})", params, intermediates, byte as char, byte); return; }} @@ -31,6 +31,7 @@ pub struct Options { pub command: Option<Shell<'static>>, pub working_dir: Option<PathBuf>, pub config: Option<PathBuf>, + pub persistent_logging: bool, } impl Default for Options { @@ -46,6 +47,7 @@ impl Default for Options { command: None, working_dir: None, config: None, + persistent_logging: false, } } } @@ -71,6 +73,9 @@ impl Options { .conflicts_with("live-config-reload")) .arg(Arg::with_name("print-events") .long("print-events")) + .arg(Arg::with_name("persistent-logging") + .long("persistent-logging") + .help("Keep the log file after quitting Alacritty")) .arg(Arg::with_name("dimensions") .long("dimensions") .short("d") @@ -129,6 +134,10 @@ impl Options { options.live_config_reload = Some(false); } + if matches.is_present("persistent-logging") { + options.persistent_logging = true; + } + if let Some(mut dimensions) = matches.values_of("dimensions") { let width = dimensions.next().map(|w| w.parse().map(Column)); let height = dimensions.next().map(|h| h.parse().map(Line)); @@ -147,8 +156,8 @@ impl Options { } match matches.occurrences_of("v") { - 0 => {}, - 1 => options.log_level = log::LevelFilter::Info, + 0 if !options.print_events => {}, + 0 | 1 => options.log_level = log::LevelFilter::Info, 2 => options.log_level = log::LevelFilter::Debug, 3 | _ => options.log_level = log::LevelFilter::Trace } diff --git a/src/config.rs b/src/config.rs index ee30c085..ae1ec897 100644 --- a/src/config.rs +++ b/src/config.rs @@ -73,7 +73,7 @@ fn deserialize_duration_ms<'a, D>(deserializer: D) -> ::std::result::Result<Dura match u64::deserialize(deserializer) { Ok(threshold_ms) => Ok(Duration::from_millis(threshold_ms)), Err(err) => { - eprintln!("problem with config: {}; Using default value", err); + error!("problem with config: {}; Using default value", err); Ok(default_threshold_ms()) }, } @@ -172,7 +172,7 @@ fn deserialize_visual_bell_duration<'a, D>(deserializer: D) -> ::std::result::Re match u16::deserialize(deserializer) { Ok(duration) => Ok(duration), Err(err) => { - eprintln!("problem with config: {}; Using default value", err); + error!("problem with config: {}; Using default value", err); Ok(default_visual_bell_duration()) }, } @@ -310,19 +310,19 @@ impl<'de> Deserialize<'de> for Decorations { "none" => Ok(Decorations::None), "full" => Ok(Decorations::Full), "true" => { - eprintln!("deprecated decorations boolean value, \ + error!("deprecated decorations boolean value, \ use one of transparent|buttonless|none|full instead; \ Falling back to \"full\""); Ok(Decorations::Full) }, "false" => { - eprintln!("deprecated decorations boolean value, \ + error!("deprecated decorations boolean value, \ use one of transparent|buttonless|none|full instead; \ Falling back to \"none\""); Ok(Decorations::None) }, _ => { - eprintln!("invalid decorations value: {}; Using default value", value); + error!("invalid decorations value: {}; Using default value", value); Ok(Decorations::Full) } } @@ -336,23 +336,23 @@ impl<'de> Deserialize<'de> for Decorations { "none" => Ok(Decorations::None), "full" => Ok(Decorations::Full), "true" => { - eprintln!("deprecated decorations boolean value, \ + error!("deprecated decorations boolean value, \ use one of none|full instead; \ Falling back to \"full\""); Ok(Decorations::Full) }, "false" => { - eprintln!("deprecated decorations boolean value, \ + error!("deprecated decorations boolean value, \ use one of none|full instead; \ Falling back to \"none\""); Ok(Decorations::None) }, "transparent" | "buttonless" => { - eprintln!("macos-only decorations value: {}; Using default value", value); + error!("macos-only decorations value: {}; Using default value", value); Ok(Decorations::Full) }, _ => { - eprintln!("invalid decorations value: {}; Using default value", value); + error!("invalid decorations value: {}; Using default value", value); Ok(Decorations::Full) } } @@ -392,7 +392,7 @@ fn deserialize_padding<'a, D>(deserializer: D) -> ::std::result::Result<Delta<u8 match Delta::deserialize(deserializer) { Ok(delta) => Ok(delta), Err(err) => { - eprintln!("problem with config: {}; Using default value", err); + error!("problem with config: {}; Using default value", err); Ok(default_padding()) }, } @@ -503,6 +503,10 @@ pub struct Config { #[serde(default, deserialize_with="failure_default")] cursor: Cursor, + /// Keep the log file after quitting + #[serde(default, deserialize_with="failure_default")] + persistent_logging: bool, + // TODO: DEPRECATED #[serde(default, deserialize_with = "failure_default")] custom_cursor_colors: Option<bool>, @@ -528,7 +532,7 @@ fn failure_default_vec<'a, D, T>(deserializer: D) -> ::std::result::Result<Vec<T let vec = match Vec::<serde_yaml::Value>::deserialize(deserializer) { Ok(vec) => vec, Err(err) => { - eprintln!("problem with config: {}; Using empty vector", err); + error!("problem with config: {}; Using empty vector", err); return Ok(Vec::new()); }, }; @@ -539,7 +543,7 @@ fn failure_default_vec<'a, D, T>(deserializer: D) -> ::std::result::Result<Vec<T match T::deserialize(value) { Ok(binding) => bindings.push(binding), Err(err) => { - eprintln!("problem with config: {}; Skipping value", err); + error!("problem with config: {}; Skipping value", err); }, } } @@ -557,7 +561,7 @@ fn deserialize_tabspaces<'a, D>(deserializer: D) -> ::std::result::Result<usize, match usize::deserialize(deserializer) { Ok(value) => Ok(value), Err(err) => { - eprintln!("problem with config: {}; Using `8`", err); + error!("problem with config: {}; Using `8`", err); Ok(default_tabspaces()) }, } @@ -569,7 +573,7 @@ fn default_true_bool<'a, D>(deserializer: D) -> ::std::result::Result<bool, D::E match bool::deserialize(deserializer) { Ok(value) => Ok(value), Err(err) => { - eprintln!("problem with config: {}; Using `true`", err); + error!("problem with config: {}; Using `true`", err); Ok(true) }, } @@ -583,7 +587,7 @@ fn failure_default<'a, D, T>(deserializer: D) match T::deserialize(deserializer) { Ok(value) => Ok(value), Err(err) => { - eprintln!("problem with config: {}; Using default value", err); + error!("problem with config: {}; Using default value", err); Ok(T::default()) }, } @@ -645,7 +649,7 @@ fn deserialize_scrolling_history<'a, D>(deserializer: D) -> ::std::result::Resul match u32::deserialize(deserializer) { Ok(lines) => { if lines > MAX_SCROLLBACK_LINES { - eprintln!( + error!( "problem with config: scrollback size is {}, but expected a maximum of {}; \ Using {1} instead", lines, MAX_SCROLLBACK_LINES, @@ -656,7 +660,7 @@ fn deserialize_scrolling_history<'a, D>(deserializer: D) -> ::std::result::Resul } }, Err(err) => { - eprintln!("problem with config: {}; Using default value", err); + error!("problem with config: {}; Using default value", err); Ok(default_scrolling_history()) }, } @@ -668,7 +672,7 @@ fn deserialize_scrolling_multiplier<'a, D>(deserializer: D) -> ::std::result::Re match u8::deserialize(deserializer) { Ok(lines) => Ok(lines), Err(err) => { - eprintln!("problem with config: {}; Using default value", err); + error!("problem with config: {}; Using default value", err); Ok(default_scrolling_multiplier()) }, } @@ -710,7 +714,7 @@ impl<'a> de::Deserialize<'a> for ModsWrapper { "Shift" => res.shift = true, "Alt" | "Option" => res.alt = true, "Control" => res.ctrl = true, - _ => eprintln!("unknown modifier {:?}", modifier), + _ => error!("unknown modifier {:?}", modifier), } } @@ -831,7 +835,7 @@ impl<'a> de::Deserialize<'a> for ModeWrapper { "~AppCursor" => res.not_mode |= mode::TermMode::APP_CURSOR, "AppKeypad" => res.mode |= mode::TermMode::APP_KEYPAD, "~AppKeypad" => res.not_mode |= mode::TermMode::APP_KEYPAD, - _ => eprintln!("unknown mode {:?}", modifier), + _ => error!("unknown mode {:?}", modifier), } } @@ -1193,7 +1197,7 @@ fn deserialize_color_index<'a, D>(deserializer: D) -> ::std::result::Result<u8, match u8::deserialize(deserializer) { Ok(index) => { if index < 16 { - eprintln!( + error!( "problem with config: indexed_color's index is '{}', \ but a value bigger than 15 was expected; \ Ignoring setting", @@ -1207,7 +1211,7 @@ fn deserialize_color_index<'a, D>(deserializer: D) -> ::std::result::Result<u8, } }, Err(err) => { - eprintln!("problem with config: {}; Ignoring setting", err); + error!("problem with config: {}; Ignoring setting", err); // Return value out of range to ignore this color Ok(0) @@ -1262,7 +1266,7 @@ fn deserialize_optional_color<'a, D>(deserializer: D) -> ::std::result::Result<O }, Ok(None) => Ok(None), Err(err) => { - eprintln!("problem with config: {}; Using standard foreground color", err); + error!("problem with config: {}; Using standard foreground color", err); Ok(None) }, } @@ -1361,7 +1365,7 @@ fn rgb_from_hex<'a, D>(deserializer: D) -> ::std::result::Result<Rgb, D::Error> match rgb { Ok(rgb) => Ok(rgb), Err(err) => { - eprintln!("problem with config: {}; Using color #ff00ff", err); + error!("problem with config: {}; Using color #ff00ff", err); Ok(Rgb { r: 255, g: 0, b: 255 }) }, } @@ -1671,6 +1675,12 @@ impl Config { self.scrolling.history = history; } + /// Keep the log file after quitting Alacritty + #[inline] + pub fn persistent_logging(&self) -> bool { + self.persistent_logging + } + pub fn load_from<P: Into<PathBuf>>(path: P) -> Result<Config> { let path = path.into(); let raw = Config::read_file(path.as_path())?; @@ -1701,24 +1711,22 @@ impl Config { } fn print_deprecation_warnings(&mut self) { - use ::util::fmt; if self.dimensions.is_some() { - eprintln!("{}", fmt::Yellow("Config `dimensions` is deprecated. \ - Please use `window.dimensions` instead.")); + warn!("{}", "Config `dimensions` is deprecated. \ + Please use `window.dimensions` instead."); } if self.padding.is_some() { - eprintln!("{}", fmt::Yellow("Config `padding` is deprecated. \ - Please use `window.padding` instead.")); + warn!("{}", "Config `padding` is deprecated. Please use `window.padding` instead."); } if self.mouse.faux_scrollback_lines.is_some() { - println!("{}", fmt::Yellow("Config `mouse.faux_scrollback_lines` is deprecated. \ - Please use `mouse.faux_scrolling_lines` instead.")); + warn!("{}", "Config `mouse.faux_scrollback_lines` is deprecated. \ + Please use `mouse.faux_scrolling_lines` instead."); } if let Some(custom_cursor_colors) = self.custom_cursor_colors { - eprintln!("{}", fmt::Yellow("Config `custom_cursor_colors` is deprecated.")); + warn!("{}", "Config `custom_cursor_colors` is deprecated."); if !custom_cursor_colors { self.colors.cursor.cursor = None; @@ -1727,18 +1735,17 @@ impl Config { } if self.cursor_style.is_some() { - eprintln!("{}", fmt::Yellow("Config `cursor_style` is deprecated. \ - Please use `cursor.style` instead.")); + warn!("{}", "Config `cursor_style` is deprecated. Please use `cursor.style` instead."); } if self.hide_cursor_when_typing.is_some() { - eprintln!("{}", fmt::Yellow("Config `hide_cursor_when_typing` is deprecated. \ - Please use `mouse.hide_when_typing` instead.")); + warn!("{}", "Config `hide_cursor_when_typing` is deprecated. \ + Please use `mouse.hide_when_typing` instead."); } if self.unfocused_hollow_cursor.is_some() { - eprintln!("{}", fmt::Yellow("Config `unfocused_hollow_cursor` is deprecated. \ - Please use `cursor.unfocused_hollow` instead.")); + warn!("{}", "Config `unfocused_hollow_cursor` is deprecated. \ + Please use `cursor.unfocused_hollow` instead."); } } } @@ -1839,7 +1846,7 @@ impl DeserializeSize for Size { match size { Ok(size) => Ok(size), Err(err) => { - eprintln!("problem with config: {}; Using size 12", err); + error!("problem with config: {}; Using size 12", err); Ok(Size::new(12.)) }, } @@ -2062,7 +2069,7 @@ impl Monitor { let _ = config_tx.send(config); handler.on_config_reload(); }, - Err(err) => eprintln!("Ignoring invalid config: {}", err), + Err(err) => error!("Ignoring invalid config: {}", err), } } } diff --git a/src/display.rs b/src/display.rs index 1a145185..12842649 100644 --- a/src/display.rs +++ b/src/display.rs @@ -28,6 +28,7 @@ use renderer::{self, GlyphCache, QuadRenderer}; use term::{Term, SizeInfo, RenderableCell}; use sync::FairMutex; use window::{self, Window}; +use logging::LoggerProxy; use Rgb; #[derive(Debug)] @@ -99,6 +100,7 @@ pub struct Display { meter: Meter, font_size: font::Size, size_info: SizeInfo, + logger_proxy: LoggerProxy, } /// Can wakeup the render loop from other threads @@ -129,7 +131,11 @@ impl Display { &self.size_info } - pub fn new(config: &Config, options: &cli::Options) -> Result<Display, Error> { + pub fn new( + config: &Config, + options: &cli::Options, + logger_proxy: LoggerProxy + ) -> Result<Display, Error> { // Extract some properties from config let render_timer = config.render_timer(); @@ -218,6 +224,7 @@ impl Display { meter: Meter::new(), font_size: font::Size::new(0.), size_info, + logger_proxy, }) } @@ -420,10 +427,38 @@ impl Display { g: 0x4e, b: 0x53, }; - self.renderer - .with_api(config, &size_info, visual_bell_intensity, |mut api| { - api.render_string(&timing[..], glyph_cache, color); - }); + self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| { + api.render_string(&timing[..], size_info.lines() - 2, glyph_cache, color); + }); + } + + // Display errors and warnings + if self.logger_proxy.errors() { + let msg = match self.logger_proxy.log_path() { + Some(path) => format!(" ERROR! See log at {} ", path), + None => " ERROR! See log in stderr ".into(), + }; + let color = Rgb { + r: 0xff, + g: 0x00, + b: 0x00, + }; + self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| { + api.render_string(&msg, size_info.lines() - 1, glyph_cache, color); + }); + } else if self.logger_proxy.warnings() { + let msg = match self.logger_proxy.log_path() { + Some(path) => format!(" WARNING! See log at {} ", path), + None => " WARNING! See log in stderr ".into(), + }; + let color = Rgb { + r: 0xff, + g: 0xff, + b: 0x00, + }; + self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| { + api.render_string(&msg, size_info.lines() - 1, glyph_cache, color); + }); } } diff --git a/src/event.rs b/src/event.rs index 7a1faa70..ece8ec6f 100644 --- a/src/event.rs +++ b/src/event.rs @@ -488,7 +488,7 @@ impl<N: Notify> Processor<N> { let hide_mouse = &mut self.hide_mouse; let mut process = |event| { if print_events { - println!("glutin event: {:?}", event); + info!("glutin event: {:?}", event); } Processor::handle_event( &mut processor, diff --git a/src/grid/tests.rs b/src/grid/tests.rs index e136e3b3..9cb30a7f 100644 --- a/src/grid/tests.rs +++ b/src/grid/tests.rs @@ -20,19 +20,13 @@ use index::{Point, Line, Column}; // Scroll up moves lines upwards #[test] fn scroll_up() { - println!(); - let mut grid = Grid::new(Line(10), Column(1), 0, 0); for i in 0..10 { grid[Line(i)][Column(0)] = i; } - println!("grid: {:?}", grid); - grid.scroll_up(&(Line(0)..Line(10)), Line(2), &0); - println!("grid: {:?}", grid); - assert_eq!(grid[Line(0)][Column(0)], 2); assert_eq!(grid[Line(0)].occ, 1); assert_eq!(grid[Line(1)][Column(0)], 3); @@ -58,19 +52,13 @@ fn scroll_up() { // Scroll down moves lines downwards #[test] fn scroll_down() { - println!(); - let mut grid = Grid::new(Line(10), Column(1), 0, 0); for i in 0..10 { grid[Line(i)][Column(0)] = i; } - println!("grid: {:?}", grid); - grid.scroll_down(&(Line(0)..Line(10)), Line(2), &0); - println!("grid: {:?}", grid); - assert_eq!(grid[Line(0)][Column(0)], 0); // was 8 assert_eq!(grid[Line(0)].occ, 0); assert_eq!(grid[Line(1)][Column(0)], 0); // was 9 diff --git a/src/input.rs b/src/input.rs index 600a1abe..d2f8f6b5 100644 --- a/src/input.rs +++ b/src/input.rs @@ -218,7 +218,7 @@ impl Action { .and_then(|clipboard| clipboard.load_primary() ) .map(|contents| { self.paste(ctx, &contents) }) .unwrap_or_else(|err| { - eprintln!("Error loading data from clipboard. {}", Red(err)); + error!("Error loading data from clipboard. {}", Red(err)); }); }, Action::PasteSelection => { @@ -228,7 +228,7 @@ impl Action { .and_then(|clipboard| clipboard.load_selection() ) .map(|contents| { self.paste(ctx, &contents) }) .unwrap_or_else(|err| { - warn!("Error loading data from clipboard. {}", Red(err)); + error!("Error loading data from clipboard. {}", Red(err)); }); } }, @@ -64,6 +64,7 @@ extern crate xdg; extern crate base64; extern crate terminfo; extern crate url; +extern crate time; #[macro_use] pub mod macros; diff --git a/src/logging.rs b/src/logging.rs index 10929980..5ad1dcd5 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -17,37 +17,134 @@ //! The main executable is supposed to call `initialize()` exactly once during //! startup. All logging messages are written to stdout, given that their //! log-level is sufficient for the level configured in `cli::Options`. -use log; -use std::sync; -use std::io; use cli; +use log::{self, Level}; +use time; -pub struct Logger<T> { +use std::env; +use std::fs::{self, File, OpenOptions}; +use std::io::{self, LineWriter, Stdout, Write}; +use std::path::PathBuf; +use std::process; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::{Arc, Mutex}; + +pub fn initialize(options: &cli::Options) -> Result<LoggerProxy, log::SetLoggerError> { + // Use env_logger if RUST_LOG environment variable is defined. Otherwise, + // use the alacritty-only logger. + if ::std::env::var("RUST_LOG").is_ok() { + ::env_logger::try_init()?; + Ok(LoggerProxy::default()) + } else { + let logger = Logger::new(options.log_level); + let proxy = logger.proxy(); + + log::set_boxed_logger(Box::new(logger))?; + + Ok(proxy) + } +} + +/// Proxy object for bidirectional communicating with the global logger. +#[derive(Clone, Default)] +pub struct LoggerProxy { + errors: Arc<AtomicBool>, + warnings: Arc<AtomicBool>, + logfile_proxy: OnDemandLogFileProxy, +} + +impl LoggerProxy { + /// Check for new logged errors. + pub fn errors(&self) -> bool { + self.errors.load(Ordering::Relaxed) + } + + /// Check for new logged warnings. + pub fn warnings(&self) -> bool { + self.warnings.load(Ordering::Relaxed) + } + + /// Get the path of the log file if it has been created. + pub fn log_path(&self) -> Option<&str> { + if self.logfile_proxy.created.load(Ordering::Relaxed) { + Some(&self.logfile_proxy.path) + } else { + None + } + } + + /// Clear log warnings/errors from the Alacritty UI. + pub fn clear(&mut self) { + self.errors.store(false, Ordering::Relaxed); + self.warnings.store(false, Ordering::Relaxed); + } + + pub fn delete_log(&mut self) { + self.logfile_proxy.delete_log(); + } +} + +struct Logger { level: log::LevelFilter, - output: sync::Mutex<T> + logfile: Mutex<OnDemandLogFile>, + stdout: Mutex<LineWriter<Stdout>>, + errors: Arc<AtomicBool>, + warnings: Arc<AtomicBool>, } -impl<T: Send + io::Write> Logger<T> { +impl Logger { // False positive, see: https://github.com/rust-lang-nursery/rust-clippy/issues/734 #[cfg_attr(feature = "cargo-clippy", allow(new_ret_no_self))] - pub fn new(output: T, level: log::LevelFilter) -> Logger<io::LineWriter<T>> { + fn new(level: log::LevelFilter) -> Self { log::set_max_level(level); + + let logfile = Mutex::new(OnDemandLogFile::new()); + let stdout = Mutex::new(LineWriter::new(io::stdout())); + Logger { level, - output: sync::Mutex::new(io::LineWriter::new(output)) + logfile, + stdout, + errors: Arc::new(AtomicBool::new(false)), + warnings: Arc::new(AtomicBool::new(false)), + } + } + + fn proxy(&self) -> LoggerProxy { + LoggerProxy { + errors: self.errors.clone(), + warnings: self.warnings.clone(), + logfile_proxy: self.logfile.lock().expect("").proxy(), } } } -impl<T: Send + io::Write> log::Log for Logger<T> { +impl log::Log for Logger { fn enabled(&self, metadata: &log::Metadata) -> bool { metadata.level() <= self.level } fn log(&self, record: &log::Record) { if self.enabled(record.metadata()) && record.target().starts_with("alacritty") { - if let Ok(ref mut writer) = self.output.lock() { - let _ = writer.write_all(format!("{}\n", record.args()).as_ref()); + let msg = format!( + "[{}] [{}] {}\n", + time::now().strftime("%F %R").unwrap(), + record.level(), + record.args() + ); + + if let Ok(ref mut logfile) = self.logfile.lock() { + let _ = logfile.write_all(msg.as_ref()); + } + + if let Ok(ref mut stdout) = self.stdout.lock() { + let _ = stdout.write_all(msg.as_ref()); + } + + match record.level() { + Level::Error => self.errors.store(true, Ordering::Relaxed), + Level::Warn => self.warnings.store(true, Ordering::Relaxed), + _ => (), } } } @@ -55,12 +152,82 @@ impl<T: Send + io::Write> log::Log for Logger<T> { fn flush(&self) {} } -pub fn initialize(options: &cli::Options) -> Result<(), log::SetLoggerError> { - // Use env_logger if RUST_LOG environment variable is defined. Otherwise, - // use the alacritty-only logger. - if ::std::env::var("RUST_LOG").is_ok() { - ::env_logger::try_init() - } else { - log::set_boxed_logger(Box::new(Logger::new(io::stdout(), options.log_level))) +#[derive(Clone, Default)] +struct OnDemandLogFileProxy { + created: Arc<AtomicBool>, + path: String, +} + +impl OnDemandLogFileProxy { + fn delete_log(&mut self) { + if self.created.load(Ordering::Relaxed) && fs::remove_file(&self.path).is_ok() { + let _ = writeln!(io::stdout(), "Deleted log file at {:?}", self.path); + self.created.store(false, Ordering::Relaxed); + } + } +} + +struct OnDemandLogFile { + file: Option<LineWriter<File>>, + created: Arc<AtomicBool>, + path: PathBuf, +} + +impl OnDemandLogFile { + fn new() -> Self { + let mut path = env::temp_dir(); + path.push(format!("Alacritty-{}.log", process::id())); + + OnDemandLogFile { + path, + file: None, + created: Arc::new(AtomicBool::new(false)), + } + } + + fn file(&mut self) -> Result<&mut LineWriter<File>, io::Error> { + // Allow to recreate the file if it has been deleted at runtime + if self.file.is_some() && !self.path.as_path().exists() { + self.file = None; + } + + // Create the file if it doesn't exist yet + if self.file.is_none() { + let file = OpenOptions::new() + .append(true) + .create(true) + .open(&self.path); + + match file { + Ok(file) => { + self.file = Some(io::LineWriter::new(file)); + self.created.store(true, Ordering::Relaxed); + let _ = writeln!(io::stdout(), "Created log file at {:?}", self.path); + } + Err(e) => { + let _ = writeln!(io::stdout(), "Unable to create log file: {}", e); + return Err(e); + } + } + } + + Ok(self.file.as_mut().unwrap()) + } + + fn proxy(&self) -> OnDemandLogFileProxy { + OnDemandLogFileProxy { + created: self.created.clone(), + path: self.path.to_string_lossy().to_string(), + } + } +} + +impl Write for OnDemandLogFile { + fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> { + self.file()?.write(buf) + } + + fn flush(&mut self) -> Result<(), io::Error> { + self.file()?.flush() } } diff --git a/src/macros.rs b/src/macros.rs index 464110e6..519f8b6a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -15,33 +15,7 @@ #[macro_export] macro_rules! die { ($($arg:tt)*) => {{ - eprintln!($($arg)*); + error!($($arg)*); ::std::process::exit(1); }} } - -#[macro_export] -macro_rules! maybe { - ($option:expr) => { - match $option { - Some(value) => value, - None => return None, - } - } -} - -#[macro_export] -macro_rules! print { - ($($arg:tt)*) => {{ - use std::io::Write; - let _ = write!(::std::io::stdout(), $($arg)*); - }}; -} - -#[macro_export] -macro_rules! eprint { - ($($arg:tt)*) => {{ - use std::io::Write; - let _ = write!(::std::io::stderr(), $($arg)*); - }}; -} diff --git a/src/main.rs b/src/main.rs index 11adb396..a44c8eb3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -52,7 +52,7 @@ use alacritty::event; use alacritty::event_loop::{self, EventLoop, Msg}; #[cfg(target_os = "macos")] use alacritty::locale; -use alacritty::logging; +use alacritty::logging::{self, LoggerProxy}; use alacritty::sync::FairMutex; use alacritty::term::Term; use alacritty::tty::{self, process_should_exit}; @@ -65,8 +65,13 @@ fn main() { #[cfg(windows)] unsafe { AttachConsole(ATTACH_PARENT_PROCESS); } - // Load command line options and config + // Load command line options let options = cli::Options::load(); + + // Initialize the logger as soon as possible as to capture output from other subsystems + let logger_proxy = logging::initialize(&options).expect("Unable to initialize logger"); + + // Load configuration file let config = load_config(&options).update_dynamic_title(&options); // Switch to home directory @@ -77,11 +82,9 @@ fn main() { locale::set_locale_environment(); // Run alacritty - if let Err(err) = run(config, &options) { + if let Err(err) = run(config, &options, logger_proxy) { die!("Alacritty encountered an unrecoverable error:\n\n\t{}\n", Red(err)); } - - info!("Goodbye."); } /// Load configuration @@ -98,7 +101,7 @@ fn load_config(options: &cli::Options) -> Config { }); Config::load_from(&*config_path).unwrap_or_else(|err| { - eprintln!("Error: {}; Loading default config", err); + error!("Error: {}; Loading default config", err); Config::default() }) } @@ -107,10 +110,11 @@ fn load_config(options: &cli::Options) -> Config { /// /// Creates a window, the terminal state, pty, I/O event loop, input processor, /// config change monitor, and runs the main display loop. -fn run(mut config: Config, options: &cli::Options) -> Result<(), Box<Error>> { - // Initialize the logger first as to capture output from other subsystems - logging::initialize(options)?; - +fn run( + mut config: Config, + options: &cli::Options, + mut logger_proxy: LoggerProxy, +) -> Result<(), Box<Error>> { info!("Welcome to Alacritty."); if let Some(config_path) = config.path() { info!("Configuration loaded from {}", config_path.display()); @@ -122,7 +126,7 @@ fn run(mut config: Config, options: &cli::Options) -> Result<(), Box<Error>> { // Create a display. // // The display manages a window and can draw the terminal - let mut display = Display::new(&config, options)?; + let mut display = Display::new(&config, options, logger_proxy.clone())?; info!( "PTY Dimensions: {:?} x {:?}", @@ -135,7 +139,8 @@ fn run(mut config: Config, options: &cli::Options) -> Result<(), Box<Error>> { // This object contains all of the state about what's being displayed. It's // wrapped in a clonable mutex since both the I/O loop and display need to // access it. - let terminal = Term::new(&config, display.size().to_owned()); + let mut terminal = Term::new(&config, display.size().to_owned()); + terminal.set_logger_proxy(logger_proxy.clone()); let terminal = Arc::new(FairMutex::new(terminal)); // Find the window ID for setting $WINDOWID @@ -258,5 +263,11 @@ fn run(mut config: Config, options: &cli::Options) -> Result<(), Box<Error>> { #[cfg(windows)] unsafe { FreeConsole(); } + info!("Goodbye."); + + if !options.persistent_logging && !config.persistent_logging() { + logger_proxy.delete_log(); + } + Ok(()) } diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 1a193caf..ef5a1e76 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -817,10 +817,16 @@ impl<'a> RenderApi<'a> { self.batch.clear(); } - /// Render a string in a predefined location. Used for printing render time for profiling and - /// optimization. - pub fn render_string(&mut self, string: &str, glyph_cache: &mut GlyphCache, color: Rgb) { - let line = Line(23); + + /// Render a string in a variable location. Used for printing the render timer, warnings and + /// errors. + pub fn render_string( + &mut self, + string: &str, + line: Line, + glyph_cache: &mut GlyphCache, + color: Rgb + ) { let col = Column(0); let cells = string diff --git a/src/term/mod.rs b/src/term/mod.rs index 39213ee2..0f228f86 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -31,6 +31,7 @@ use config::{Config, VisualBellAnimation}; use {MouseCursor, Rgb}; use copypasta::{Clipboard, Load, Store}; use input::FONT_SIZE_STEP; +use logging::LoggerProxy; pub mod cell; pub mod color; @@ -810,6 +811,9 @@ pub struct Term { /// Automatically scroll to bottom when new lines are added auto_scroll: bool, + + /// Proxy object for clearing displayed errors and warnings + logger_proxy: Option<LoggerProxy>, } /// Terminal size info @@ -936,9 +940,14 @@ impl Term { dynamic_title: config.dynamic_title(), tabspaces, auto_scroll: config.scrolling().auto_scroll, + logger_proxy: None, } } + pub fn set_logger_proxy(&mut self, logger_proxy: LoggerProxy) { + self.logger_proxy = Some(logger_proxy); + } + pub fn change_font_size(&mut self, delta: f32) { // Saturating addition with minimum font size FONT_SIZE_STEP let new_size = self.font_size + Size::new(delta); @@ -1822,6 +1831,11 @@ impl ansi::Handler for Term { } }, ansi::ClearMode::All => { + // Clear displayed errors and warnings + if let Some(ref mut logger_proxy) = self.logger_proxy { + logger_proxy.clear(); + } + self.grid.region_mut(..).each(|c| c.reset(&template)); }, ansi::ClearMode::Above => { |