Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:26
erlang
2630-shell-Fix-latin1-handling-for-shell-prompt...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 2630-shell-Fix-latin1-handling-for-shell-prompt_width.patch of Package erlang
From 3257119108b574dbd7a61657a49d373a264b5831 Mon Sep 17 00:00:00 2001 From: Lukas Larsson <lukas@erlang.org> Date: Fri, 5 Jan 2024 09:40:49 +0100 Subject: [PATCH 10/11] shell: Fix latin1 handling for shell:prompt_width --- lib/kernel/src/prim_tty.erl | 7 +++++-- lib/stdlib/doc/src/shell.xml | 26 ++++++++++++++++++++++++++ lib/stdlib/src/shell.erl | 20 +++++++++++--------- lib/stdlib/test/shell_SUITE.erl | 20 +++++++++++++++++--- 4 files changed, 59 insertions(+), 14 deletions(-) diff --git a/lib/kernel/src/prim_tty.erl b/lib/kernel/src/prim_tty.erl index b8413cb090..67e873029b 100644 --- a/lib/kernel/src/prim_tty.erl +++ b/lib/kernel/src/prim_tty.erl @@ -105,7 +105,8 @@ %% to previous line automatically. -export([init/1, reinit/2, isatty/1, handles/1, unicode/1, unicode/2, - handle_signal/2, window_size/1, handle_request/2, write/2, write/3, npwcwidth/1, + handle_signal/2, window_size/1, handle_request/2, write/2, write/3, + npwcwidth/1, npwcwidth/2, ansi_regexp/0, ansi_color/2]). -export([reader_stop/1, disable_reader/1, enable_reader/1]). @@ -1108,7 +1109,9 @@ npwcwidth(Char, true) -> C -> C end; npwcwidth(Char, false) -> - byte_size(char_to_latin1(Char, true)). + byte_size(char_to_latin1(Char, true)); +npwcwidth(Char, Encoding) -> + npwcwidth(Char, Encoding =/= latin1). %% Return the xn fix for the current cursor position. diff --git a/lib/stdlib/doc/src/shell.xml b/lib/stdlib/doc/src/shell.xml index 996ef9c0be..600c7cb32f 100644 --- a/lib/stdlib/doc/src/shell.xml +++ b/lib/stdlib/doc/src/shell.xml @@ -1035,10 +1035,36 @@ q - quit erlang <func> <name name="prompt_width" arity="1" since="OTP 27.0"/> <fsummary>Computes the width of a prompt.</fsummary> + <desc> + <p>Equivalent to <seemfa marker="#prompt_width/2">prompt_width/2</seemfa> with + <c>Encoding</c> set to the encoding used by + <seetype marker="io#user"><c>io:user/0</c></seetype>.</p> + </desc> + </func> + + <func> + <name name="prompt_width" arity="2" since="OTP 27.0"/> + <fsummary>Computes the width of a prompt.</fsummary> <desc> <p>It receives a prompt and computes its width, considering its Unicode characters and ANSI escapes.</p> <p>Useful for creating custom multiline prompts.</p> + <p>Example:</p> + <code type="erl"> +1> shell:prompt_width("olá> ", unicode). +5 +%% "olá> " is printed as "ol\341> " on a latin1 systems +2> shell:prompt_width("olá> ", latin1). +8 +%% Ansi escapes are ignored +3> shell:prompt_width("\e[32molá\e[0m> ", unicode). +5 +%% Double width characters count as 2 +4> shell:prompt_width("😀> ", unicode). +4 +%% "😀> " is printed as "\x{1F600}> " on latin1 systems +5> shell:prompt_width("😀> ", latin1). +11</code> </desc> </func> diff --git a/lib/stdlib/src/shell.erl b/lib/stdlib/src/shell.erl index 5164023290..a230ee48c6 100644 --- a/lib/stdlib/src/shell.erl +++ b/lib/stdlib/src/shell.erl @@ -28,7 +28,7 @@ -export([start_interactive/0, start_interactive/1]). -export([read_and_add_records/5]). -export([default_multiline_prompt/1, inverted_space_prompt/1]). --export([prompt_width/1]). +-export([prompt_width/1, prompt_width/2]). -export([whereis/0]). -define(LINEMAX, 30). @@ -1907,22 +1907,24 @@ strings(Strings) -> set_env(stdlib, shell_strings, Strings, ?DEF_STRINGS). -spec prompt_width(unicode:chardata()) -> non_neg_integer(). - -prompt_width(String) when is_list(String) -> - prompt_width(unicode:characters_to_binary(String)); prompt_width(String) -> + Encoding = proplists:get_value(encoding, io:getopts(user)), + prompt_width(String, Encoding). + +-spec prompt_width(unicode:chardata(), unicode | latin1) -> non_neg_integer(). +prompt_width(String, Encoding) -> case string:next_grapheme(String) of [] -> 0; [$\e | Rest] -> case re:run(String, prim_tty:ansi_regexp(), [unicode]) of {match, [{0, N}]} -> - <<_Ansi:N/binary, AnsiRest/binary>> = String, - prompt_width(AnsiRest); + <<_Ansi:N/binary, AnsiRest/binary>> = unicode:characters_to_binary(String), + prompt_width(AnsiRest, Encoding); _ -> - prim_tty:npwcwidth($\e) + prompt_width(Rest) + prim_tty:npwcwidth($\e, Encoding) + prompt_width(Rest, Encoding) end; - [H|Rest] when is_list(H)-> lists:sum([prim_tty:npwcwidth(A)||A<-H]) + prompt_width(Rest); - [H|Rest] -> prim_tty:npwcwidth(H) + prompt_width(Rest) + [H|Rest] when is_list(H)-> lists:sum([prim_tty:npwcwidth(A, Encoding)||A<-H]) + prompt_width(Rest, Encoding); + [H|Rest] -> prim_tty:npwcwidth(H, Encoding) + prompt_width(Rest, Encoding) end. -spec default_multiline_prompt(unicode:chardata()) -> diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl index 4913dbb060..55e8cca0ab 100644 --- a/lib/stdlib/test/shell_SUITE.erl +++ b/lib/stdlib/test/shell_SUITE.erl @@ -25,7 +25,7 @@ bs_match_misc_SUITE/1, bs_match_int_SUITE/1, bs_match_tail_SUITE/1, bs_match_bin_SUITE/1, bs_construct_SUITE/1, - prompt_width/1,local_definitions_save_to_module_and_forget/1, + prompt_width/1,local_definitions_save_to_module_and_forget/1, refman_bit_syntax/1, progex_bit_syntax/1, progex_records/1, progex_lc/1, progex_funs/1, @@ -425,8 +425,22 @@ shell_attribute_test(Config) -> ok. prompt_width(Config) when is_list(Config) -> - 5 = shell:prompt_width("\e[31molá> "), - 5 = shell:prompt_width(<<"\e[31molá> "/utf8>>), + 5 = shell:prompt_width("olá> ", unicode), + 5 = shell:prompt_width("\e[31molá> ", unicode), + 5 = shell:prompt_width(<<"\e[31molá> "/utf8>>, unicode), + 8 = shell:prompt_width("olá> ", latin1), + 4 = shell:prompt_width("😀> ", unicode), + 11 = shell:prompt_width("😀> ", latin1), + case proplists:get_value(encoding, io:getopts(user)) of + unicode -> + 5 = shell:prompt_width("olá> "), + 5 = shell:prompt_width("\e[31molá> "), + 5 = shell:prompt_width(<<"\e[31molá> "/utf8>>), + 4 = shell:prompt_width("😀> "); + latin1 -> + 8 = shell:prompt_width("olá> "), + 11 = shell:prompt_width("😀> ") + end, ok. %% Test of the record support. OTP-5063. -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor