From 4b0b1a5657b78693efe609647360de30264fcc92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matou=C5=A1=20Dzivjak?= Date: Sat, 25 Dec 2021 16:10:46 +0100 Subject: [PATCH] feat(ui): file encoding in statusline (#1355) * feat(ui): file encoding in statusline Display file encoding in statusline if the encoding isn't UTF-8. * Re-export encoding_rs from core From there it can be imported by other mods that rely on it. --- Cargo.lock | 2 +- helix-core/Cargo.toml | 1 + helix-core/src/lib.rs | 2 ++ helix-term/src/ui/editor.rs | 9 ++++++++- helix-view/Cargo.toml | 1 - helix-view/src/document.rs | 33 +++++++++++++++++---------------- 6 files changed, 29 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 27268feb0..40afe4e50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -370,6 +370,7 @@ version = "0.5.0" dependencies = [ "arc-swap", "chrono", + "encoding_rs", "etcetera", "helix-syntax", "log", @@ -471,7 +472,6 @@ dependencies = [ "chardetng", "clipboard-win", "crossterm", - "encoding_rs", "futures-util", "helix-core", "helix-lsp", diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml index 839b07ac1..3d7fe8662 100644 --- a/helix-core/Cargo.toml +++ b/helix-core/Cargo.toml @@ -35,6 +35,7 @@ toml = "0.5" similar = "2.1" etcetera = "0.3" +encoding_rs = "0.8" chrono = { version = "0.4", default-features = false, features = ["alloc", "std"] } diff --git a/helix-core/src/lib.rs b/helix-core/src/lib.rs index 92a59f31e..1c78e7c0b 100644 --- a/helix-core/src/lib.rs +++ b/helix-core/src/lib.rs @@ -1,3 +1,5 @@ +pub use encoding_rs as encoding; + pub mod auto_pairs; pub mod chars; pub mod comment; diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 390b37595..dd0503981 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -7,7 +7,7 @@ }; use helix_core::{ - coords_at_pos, + coords_at_pos, encoding, graphemes::{ensure_grapheme_boundary_next, next_grapheme_boundary, prev_grapheme_boundary}, movement::Direction, syntax::{self, HighlightEvent}, @@ -621,6 +621,13 @@ pub fn render_statusline( base_style, )); + let enc = doc.encoding(); + if enc != encoding::UTF_8 { + right_side_text + .0 + .push(Span::styled(format!(" {} ", enc.name()), base_style)); + } + // Render to the statusline. surface.set_spans( viewport.x diff --git a/helix-view/Cargo.toml b/helix-view/Cargo.toml index 9c3a83f81..121a518c3 100644 --- a/helix-view/Cargo.toml +++ b/helix-view/Cargo.toml @@ -29,7 +29,6 @@ futures-util = { version = "0.3", features = ["std", "async-await"], default-fea slotmap = "1" -encoding_rs = "0.8" chardetng = "0.1" serde = { version = "1.0", features = ["derive"] } diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index c71d1850a..9652d7b3c 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -9,6 +9,7 @@ use std::sync::Arc; use helix_core::{ + encoding, history::History, indent::{auto_detect_indent_style, IndentStyle}, line_ending::auto_detect_line_ending, @@ -74,7 +75,7 @@ pub struct Document { pub(crate) selections: HashMap, path: Option, - encoding: &'static encoding_rs::Encoding, + encoding: &'static encoding::Encoding, /// Current editing mode. pub mode: Mode, @@ -143,8 +144,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// be used to override encoding auto-detection. pub fn from_reader( reader: &mut R, - encoding: Option<&'static encoding_rs::Encoding>, -) -> Result<(Rope, &'static encoding_rs::Encoding), Error> { + encoding: Option<&'static encoding::Encoding>, +) -> Result<(Rope, &'static encoding::Encoding), Error> { // These two buffers are 8192 bytes in size each and are used as // intermediaries during the decoding process. Text read into `buf` // from `reader` is decoded into `buf_out` as UTF-8. Once either @@ -212,11 +213,11 @@ pub fn from_reader( total_read += read; total_written += written; match result { - encoding_rs::CoderResult::InputEmpty => { + encoding::CoderResult::InputEmpty => { debug_assert_eq!(slice.len(), total_read); break; } - encoding_rs::CoderResult::OutputFull => { + encoding::CoderResult::OutputFull => { debug_assert!(slice.len() > total_read); builder.append(&buf_str[..total_written]); total_written = 0; @@ -251,7 +252,7 @@ pub fn from_reader( /// replacement characters may appear in the encoded text. pub async fn to_writer<'a, W: tokio::io::AsyncWriteExt + Unpin + ?Sized>( writer: &'a mut W, - encoding: &'static encoding_rs::Encoding, + encoding: &'static encoding::Encoding, rope: &'a Rope, ) -> Result<(), Error> { // Text inside a `Rope` is stored as non-contiguous blocks of data called @@ -286,12 +287,12 @@ pub async fn to_writer<'a, W: tokio::io::AsyncWriteExt + Unpin + ?Sized>( total_read += read; total_written += written; match result { - encoding_rs::CoderResult::InputEmpty => { + encoding::CoderResult::InputEmpty => { debug_assert_eq!(chunk.len(), total_read); debug_assert!(buf.len() >= total_written); break; } - encoding_rs::CoderResult::OutputFull => { + encoding::CoderResult::OutputFull => { debug_assert!(chunk.len() > total_read); writer.write_all(&buf[..total_written]).await?; total_written = 0; @@ -322,8 +323,8 @@ fn take_with(mut_ref: &mut T, f: F) use url::Url; impl Document { - pub fn from(text: Rope, encoding: Option<&'static encoding_rs::Encoding>) -> Self { - let encoding = encoding.unwrap_or(encoding_rs::UTF_8); + pub fn from(text: Rope, encoding: Option<&'static encoding::Encoding>) -> Self { + let encoding = encoding.unwrap_or(encoding::UTF_8); let changes = ChangeSet::new(&text); let old_state = None; @@ -356,7 +357,7 @@ pub fn from(text: Rope, encoding: Option<&'static encoding_rs::Encoding>) -> Sel /// overwritten with the `encoding` parameter. pub fn open( path: &Path, - encoding: Option<&'static encoding_rs::Encoding>, + encoding: Option<&'static encoding::Encoding>, theme: Option<&Theme>, config_loader: Option<&syntax::Loader>, ) -> Result { @@ -366,7 +367,7 @@ pub fn open( std::fs::File::open(path).context(format!("unable to open {:?}", path))?; from_reader(&mut file, encoding)? } else { - let encoding = encoding.unwrap_or(encoding_rs::UTF_8); + let encoding = encoding.unwrap_or(encoding::UTF_8); (Rope::from(DEFAULT_LINE_ENDING.as_str()), encoding) }; @@ -548,7 +549,7 @@ pub fn reload(&mut self, view_id: ViewId) -> Result<(), Error> { /// Sets the [`Document`]'s encoding with the encoding correspondent to `label`. pub fn set_encoding(&mut self, label: &str) -> Result<(), Error> { - match encoding_rs::Encoding::for_label(label.as_bytes()) { + match encoding::Encoding::for_label(label.as_bytes()) { Some(encoding) => self.encoding = encoding, None => return Err(anyhow::anyhow!("unknown encoding")), } @@ -556,7 +557,7 @@ pub fn set_encoding(&mut self, label: &str) -> Result<(), Error> { } /// Returns the [`Document`]'s current encoding. - pub fn encoding(&self) -> &'static encoding_rs::Encoding { + pub fn encoding(&self) -> &'static encoding::Encoding { self.encoding } @@ -1123,7 +1124,7 @@ fn test_line_ending() { macro_rules! test_decode { ($label:expr, $label_override:expr) => { - let encoding = encoding_rs::Encoding::for_label($label_override.as_bytes()).unwrap(); + let encoding = encoding::Encoding::for_label($label_override.as_bytes()).unwrap(); let base_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/encoding"); let path = base_path.join(format!("{}_in.txt", $label)); let ref_path = base_path.join(format!("{}_in_ref.txt", $label)); @@ -1142,7 +1143,7 @@ macro_rules! test_decode { macro_rules! test_encode { ($label:expr, $label_override:expr) => { - let encoding = encoding_rs::Encoding::for_label($label_override.as_bytes()).unwrap(); + let encoding = encoding::Encoding::for_label($label_override.as_bytes()).unwrap(); let base_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/encoding"); let path = base_path.join(format!("{}_out.txt", $label)); let ref_path = base_path.join(format!("{}_out_ref.txt", $label));