From 622553e40e60dade69ba5b62730ddb8797c7b222 Mon Sep 17 00:00:00 2001 From: Joshua Reusch Date: Wed, 16 Oct 2024 18:27:01 +0200 Subject: [PATCH] remove record update syntax for perf --- src/string_width.gleam | 157 ++++++++++++++++++++++++++++------------- 1 file changed, 106 insertions(+), 51 deletions(-) diff --git a/src/string_width.gleam b/src/string_width.gleam index e12de2d..bd72928 100644 --- a/src/string_width.gleam +++ b/src/string_width.gleam @@ -1,5 +1,5 @@ //// The `with` variants of function additionally work with custom options. -//// +//// //// #### Measure //// [line](#line)[[_with](#line_with)] //// [dimensions](#dimensions)[[_with](#dimensions_with)], @@ -11,7 +11,7 @@ //// [align](#align)[[_with](#align_with)], //// [tabs_to_spaces](#tabs_to_spaces)[[_with](#tabs_to_spaces_with)], //// [inline_styles](#inline_styles) -//// +//// //// #### Options Builder //// [new](#new), //// [ambiguous_as_wide](#ambiguous_as_wide), [count_ansi_codes](#count_ansi_codes), @@ -91,7 +91,7 @@ const default_options = Options( ) /// Start building up new options. -/// +/// ///
/// /// Back to top ↑ @@ -117,7 +117,7 @@ pub fn new() -> Options { /// /// See also [Grapheme Clusters and Terminal Emulators](https://mitchellh.com/writing/grapheme-clusters-in-terminals) /// for a better explanation on how terminals behave. -/// +/// ///
/// /// Back to top ↑ @@ -137,7 +137,7 @@ pub fn mode_2027(options: Options) -> Options { /// This mode is an additional heuristic that tries to handle more such cases. /// /// See `mode_2027` for more explanation on the implications. -/// +/// ///
/// /// Back to top ↑ @@ -154,7 +154,7 @@ pub fn mode_2027_ext(options: Options) -> Options { /// /// Note that except for `fold_raw`, this library will still always process /// grapheme clusters as a unit. -/// +/// ///
/// /// Back to top ↑ @@ -170,7 +170,7 @@ pub fn mode_wcwidth(options: Options) -> Options { /// /// Unicode recommends treating these characters as narrow by default, /// but you can change this behaviour using this option. -/// +/// ///
/// /// Back to top ↑ @@ -184,7 +184,7 @@ pub fn ambiguous_as_wide(options: Options) -> Options { /// /// You can enable this option as an optimisation if you are sure that your /// string doesn't contain any ansi escape codes. -/// +/// ///
/// /// Back to top ↑ @@ -198,7 +198,7 @@ pub fn count_ansi_codes(options: Options) -> Options { /// /// Whenever a tab character `\t` is encountered, the current column number will /// be rounded up to the next multiple of this number. -/// +/// ///
/// /// Back to top ↑ @@ -213,7 +213,7 @@ pub fn with_tab_width(options: Options, tab_width: Int) -> Options { /// If the text you print doesn't start at the first column, but is instead /// indented somehow, you can set this option to this number to make sure tab /// stops are correctly calculated. -/// +/// ///
/// /// Back to top ↑ @@ -235,7 +235,7 @@ pub type Size { /// /// Checks the built-in methods for the target, as well as the `LINES` and /// `COLUMNS` environment variables. -/// +/// ///
/// /// Back to top ↑ @@ -271,7 +271,7 @@ fn do_get_terminal_size() -> Result(#(Int, Int), Nil) /// line("\u{1B}[31mhello\u{1B}[39m") /// // --> 5 /// ``` -/// +/// ///
/// /// Back to top ↑ @@ -294,7 +294,7 @@ pub fn line(str: String) -> Int { /// line_with("👩‍👩‍👦‍👦", options) /// // --> 2 /// ``` -/// +/// ///
/// /// Back to top ↑ @@ -319,7 +319,7 @@ pub fn line_with(str: String, options: Options) -> Int { /// dimensions("hello,\n안녕하세요") /// // --> Size(rows: 2, columns: 10) /// ``` -/// +/// ///
/// /// Back to top ↑ @@ -331,7 +331,7 @@ pub fn dimensions(str: String) -> Size { } /// Like `dimensions`, but use custom options. -/// +/// ///
/// /// Back to top ↑ @@ -431,7 +431,7 @@ fn prepare_measure( /// limit("Hello World", Size(rows: 2, columns: 10), ellipsis: "...") /// // --> "Hello\nWorld" /// ``` -/// +/// ///
/// /// Back to top ↑ @@ -486,7 +486,7 @@ fn limit_state_overflow( } /// Like `limit`, but also customise the options used for measuring. -/// +/// ///
/// /// Back to top ↑ @@ -501,18 +501,6 @@ pub fn limit_with( let ellipsis_width = line_with(ellipsis, options) let max_row = max_size.rows - let initial = - LimitState( - str: "", - row: 0, - col: 0, - spaces: "", - spaces_width: 0, - non_spaces: "", - non_spaces_width: 0, - overflow: "", - overflow_width: 0, - ) // we encode a few states, but we do it this way such that spread works... // - if state.row == max_size.rows, we have reached the end and should do nothing // - if we have oveflow, we are at the last line and stuff doesn't fit. @@ -536,9 +524,15 @@ pub fn limit_with( "" -> state _ -> LimitState( - ..state, spaces: state.spaces <> piece, spaces_width: state.spaces_width + width, + str: state.str, + row: state.row, + col: state.col, + non_spaces: state.non_spaces, + non_spaces_width: state.non_spaces_width, + overflow: state.overflow, + overflow_width: state.overflow_width, ) } @@ -552,12 +546,15 @@ pub fn limit_with( let str = state.str <> state.spaces <> state.non_spaces <> state.overflow LimitState( - ..initial, str:, row: state.row, col: new_col, spaces: piece, spaces_width: width, + non_spaces: "", + non_spaces_width: 0, + overflow: "", + overflow_width: 0, ) } @@ -568,21 +565,29 @@ pub fn limit_with( let #(truncated, _, _) = limit_state_overflow(state, "", options) LimitState( - ..initial, str: state.str <> truncated <> ellipsis, row: state.row + 1, col: max_size.columns, + spaces: "", + spaces_width: 0, + non_spaces: "", + non_spaces_width: 0, + overflow: "", + overflow_width: 0, ) } False -> LimitState( - ..initial, str: state.str <> "\n" <> state.non_spaces <> state.overflow, row: state.row + 1, col: state.non_spaces_width + state.overflow_width, spaces: piece, spaces_width: width, + non_spaces: "", + non_spaces_width: 0, + overflow: "", + overflow_width: 0, ) } } @@ -590,6 +595,19 @@ pub fn limit_with( } } + let initial = + LimitState( + str: "", + row: 0, + col: 0, + spaces: "", + spaces_width: 0, + non_spaces: "", + non_spaces_width: 0, + overflow: "", + overflow_width: 0, + ) + let state = { use state, piece, width <- fold_raw(str, options, initial) // io.debug(#(state, piece, width)) @@ -603,7 +621,18 @@ pub fn limit_with( // reached the end, but we still want to collect ansi sequences True -> case is_ansi_component(piece, options) { - True -> LimitState(..state, str: state.str <> piece) + True -> + LimitState( + str: state.str <> piece, + row: state.row, + col: state.col, + spaces: state.spaces, + spaces_width: state.spaces_width, + non_spaces: state.non_spaces, + non_spaces_width: state.non_spaces_width, + overflow: state.overflow, + overflow_width: state.overflow_width, + ) False -> state } @@ -613,10 +642,15 @@ pub fn limit_with( "\n" -> { let state = commit(max_col, state, "", 0) LimitState( - ..state, str: state.str <> "\n", row: state.row + 1, col: 0, + spaces: state.spaces, + spaces_width: state.spaces_width, + non_spaces: state.non_spaces, + non_spaces_width: state.non_spaces_width, + overflow: state.overflow, + overflow_width: state.overflow_width, ) } @@ -659,9 +693,15 @@ pub fn limit_with( True -> // everything's fine and normal :) LimitState( - ..state, non_spaces: state.non_spaces <> piece, non_spaces_width: state.non_spaces_width + width, + str: state.str, + row: state.row, + col: state.col, + spaces: state.spaces, + spaces_width: state.spaces_width, + overflow: state.overflow, + overflow_width: state.overflow_width, ) False -> { @@ -678,29 +718,44 @@ pub fn limit_with( case is_last_line { False -> LimitState( - ..initial, str: state.str <> truncated <> "\n", row: state.row + 1, non_spaces: overflow, non_spaces_width: overflow_width, + col: 0, + spaces: "", + spaces_width: 0, + overflow: "", + overflow_width: 0, ) True -> // no, word to long this is the last row, sorry. LimitState( - ..initial, str: state.str <> truncated <> ellipsis, row: state.row + 1, col: max_size.columns, + spaces: "", + spaces_width: 0, + non_spaces: "", + non_spaces_width: 0, + overflow: "", + overflow_width: 0, ) } } False -> LimitState( - ..state, overflow: state.overflow <> piece, overflow_width: state.overflow_width + width, + str: state.str, + row: state.row, + col: state.col, + spaces: state.spaces, + spaces_width: state.spaces_width, + non_spaces: state.non_spaces, + non_spaces_width: state.non_spaces_width, ) } } @@ -727,7 +782,7 @@ pub fn limit_with( /// tabs_to_spaces("Hello\tWorld") /// // --> "Hello World" // 3 spaces /// ``` -/// +/// ///
/// /// Back to top ↑ @@ -747,7 +802,7 @@ pub fn tabs_to_spaces(str: String) -> String { /// tabs_to_spaces_with("hi\tcutie~", options) /// // --> "hi cutie~" /// ``` -/// +/// ///
/// /// Back to top ↑ @@ -794,7 +849,7 @@ pub type Placement { /// position("Trans\nrights\nare\nhuman\nrights", Size(0, 7), Right, Top, " ") /// // --> " Trans \n rights\n are \n human \n rights" /// ``` -/// +/// ///
/// /// Back to top ↑ @@ -811,7 +866,7 @@ pub fn position( } /// Like `position`, but use custom options to measure each line. -/// +/// ///
/// /// Back to top ↑ @@ -917,7 +972,7 @@ pub fn position_with( /// align("Trans\nrights\nare\nhuman\nrights", to: 7, align: Right, with: " ") /// // --> " Trans\n rights\n are\n human\n rights" /// ``` -/// +/// ///
/// /// Back to top ↑ @@ -933,7 +988,7 @@ pub fn align( } /// Like `align`, bu use custom options for measure. -/// +/// ///
/// /// Back to top ↑ @@ -1015,7 +1070,7 @@ fn div_up(numerator: Int, denom: Int) { /// inline_styles("\u{1b}[31mhello\nworld") /// // --> "\u{1b}[31mhello" <> "\u{1b}[m\n" <> "\u{1b}[31mworld" <> "\u{1b}[m" /// ``` -/// +/// ///
/// /// Back to top ↑ @@ -1068,7 +1123,7 @@ pub fn inline_styles(str: String) -> String { /// Returns true if a given component string recieved in `fold` is an ANSI /// escape sequence. -/// +/// ///
/// /// Back to top ↑ @@ -1096,7 +1151,7 @@ pub type Piece { /// regardless of options. Concatenating the graphemes produces the original string. /// /// Intended to be used as a basis for custom layout algorithms. -/// +/// ///