Display errors and warnings

To make sure that all error and information reporting to the user is
unified, all instances of `print!`, `eprint!`, `println!` and
`eprintln!` have been removed and replaced by logging.

When `RUST_LOG` is not specified, the default Alacritty logger now also
prints to both the stderr and a log file. The log file is only created
when a message is written to it and its name is printed to stdout the
first time it is used.

Whenever a warning or an error has been written to the log file/stderr,
a message is now displayed in Alacritty which points to the log file
where the full error is documented.

The message is cleared whenever the screen is cleared using either the
`clear` command or the `Ctrl+L` key binding.

To make sure that log files created by root don't prevent normal users
from interacting with them, the Alacritty log file is `/tmp/Alacritty-$PID.log`.

Since it's still possible that the log file can't be created, the UI
error/warning message now informs the user if the message was only
written to stderr. The reason why it couldn't be created is then printed
to stderr.

To make sure the deletion of the log file at runtime doesn't create any
issues, the file is re-created if a write is attempted without the file
being present.

To help with debugging Alacritty issues, a timestamp and the error
level are printed in all log messages.

All log messages now follow this format:
    [YYYY-MM-DD HH:MM] [LEVEL] Message

Since it's not unusual to spawn a lot of different terminal emulators
without restarting, Alacritty can create a ton of different log files.

To combat this problem, logfiles are removed by default after
Alacritty has been closed. If the user wants to persist the log of a
single session, the `--persistent_logging` option can be used. For
persisting all log files, the `persistent_logging` option can be set in
the configuration file
This commit is contained in:
Christian Duerr 2018-11-17 14:39:13 +00:00 committed by GitHub
parent ea637cde1c
commit 6265ef91d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 416 additions and 172 deletions

View File

@ -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

89
Cargo.lock generated
View File

@ -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)",
]
@ -2127,6 +2128,19 @@ dependencies = [
"remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[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"
@ -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"

View File

@ -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]

View File

@ -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

View File

@ -15,6 +15,9 @@ complete -c alacritty \
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" \

View File

@ -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)]" \

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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;
}}

View File

@ -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
}

View File

@ -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),
}
}
}

View File

@ -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);
});
}
}

View File

@ -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,

View File

@ -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

View File

@ -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));
});
}
},

View File

@ -64,6 +64,7 @@ extern crate xdg;
extern crate base64;
extern crate terminfo;
extern crate url;
extern crate time;
#[macro_use]
pub mod macros;

View File

@ -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> {
level: log::LevelFilter,
output: sync::Mutex<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)
}
}
impl<T: Send + io::Write> Logger<T> {
/// 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,
logfile: Mutex<OnDemandLogFile>,
stdout: Mutex<LineWriter<Stdout>>,
errors: Arc<AtomicBool>,
warnings: Arc<AtomicBool>,
}
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()
}
}

View File

@ -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)*);
}};
}

View File

@ -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(())
}

View File

@ -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

View File

@ -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 => {