From d48da855181356d9240d085de9e1a54e30b22e72 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 28 Jun 2026 12:45:16 +0530 Subject: [PATCH 01/10] Upgrade C++ standard so Clang supports `from_chars` --- custom-prompt/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom-prompt/Makefile b/custom-prompt/Makefile index b3c8c45f..dabdd5c1 100644 --- a/custom-prompt/Makefile +++ b/custom-prompt/Makefile @@ -1,5 +1,5 @@ CPPFLAGS = $(shell pkg-config --cflags libgit2) -CXXFLAGS = -fstrict-aliasing -std=c++17 -Wall -Wextra -Wno-unused-parameter +CXXFLAGS = -fstrict-aliasing -std=c++20 -Wall -Wextra -Wno-unused-parameter LDLIBS = -lstdc++ $(shell pkg-config --libs libgit2) MainSource = custom-prompt.cc From 5797db1cfd3cce49b16f9a2759eb997741d69064 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 28 Jun 2026 22:14:54 +0530 Subject: [PATCH 02/10] Revert "Upgrade C++ standard so Clang supports `from_chars`" This reverts commit d48da855181356d9240d085de9e1a54e30b22e72. [skip ci] --- custom-prompt/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom-prompt/Makefile b/custom-prompt/Makefile index dabdd5c1..b3c8c45f 100644 --- a/custom-prompt/Makefile +++ b/custom-prompt/Makefile @@ -1,5 +1,5 @@ CPPFLAGS = $(shell pkg-config --cflags libgit2) -CXXFLAGS = -fstrict-aliasing -std=c++20 -Wall -Wextra -Wno-unused-parameter +CXXFLAGS = -fstrict-aliasing -std=c++17 -Wall -Wextra -Wno-unused-parameter LDLIBS = -lstdc++ $(shell pkg-config --libs libgit2) MainSource = custom-prompt.cc From 8fcfcc785955a12ad363b1ab2dcf05558e3fdbb9 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 28 Jun 2026 22:19:24 +0530 Subject: [PATCH 03/10] Macro to replace repeated logic --- custom-prompt/custom-prompt.cc | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 673081a1..bac24704 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -96,6 +96,13 @@ namespace C // clang-format on +#define FROM_CHARS(type, name, value, source) \ + type name = value; \ + { \ + std::string_view name_view(source); \ + std::from_chars(name_view.data(), name_view.data() + name_view.size(), name); \ + } + static JSONLogger logger; /** @@ -757,18 +764,15 @@ int main_internal(int const argc, char const* argv[]) .detach(); std::string_view last_command(argv[1]); - int exit_code = std::stoi(argv[2]); - double begin_ts, end_ts; - std::string_view begin_ts_view(argv[3]); - std::from_chars(begin_ts_view.data(), begin_ts_view.data() + begin_ts_view.size(), begin_ts); - std::string_view end_ts_view(argv[4]); - std::from_chars(end_ts_view.data(), end_ts_view.data() + end_ts_view.size(), end_ts); + FROM_CHARS(int, exit_code, 1, argv[2]); + double begin_ts = std::strtod(argv[3], nullptr); + double end_ts = std::strtod(argv[4], nullptr); double delay = end_ts - begin_ts; - std::size_t columns = std::stoull(argv[5]); + FROM_CHARS(std::size_T, columns, 79, argv[5]); report_command_status(last_command, exit_code, delay, columns); std::string_view pwd(argv[6]); - int shlvl = std::stoi(argv[7]); + FROM_CHARS(int, shlvl, 1, argv[7]); std::string_view venv_view; char const* venv; if ((venv = getenv("VIRTUAL_ENV_PROMPT")) != nullptr) From 0c50913f58a829160c0bef7589a36a1818cb38de Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 28 Jun 2026 22:21:46 +0530 Subject: [PATCH 04/10] Typo [skip ci] --- custom-prompt/custom-prompt.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index bac24704..79b71b3e 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -768,7 +768,7 @@ int main_internal(int const argc, char const* argv[]) double begin_ts = std::strtod(argv[3], nullptr); double end_ts = std::strtod(argv[4], nullptr); double delay = end_ts - begin_ts; - FROM_CHARS(std::size_T, columns, 79, argv[5]); + FROM_CHARS(std::size_t, columns, 79, argv[5]); report_command_status(last_command, exit_code, delay, columns); std::string_view pwd(argv[6]); From 2d47d7bee17b4181cad8099c94d220a8a1a2836a Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 28 Jun 2026 22:40:23 +0530 Subject: [PATCH 05/10] Replace macro with function --- custom-prompt/custom-prompt.cc | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 79b71b3e..d1ccdc25 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -96,15 +96,23 @@ namespace C // clang-format on -#define FROM_CHARS(type, name, value, source) \ - type name = value; \ - { \ - std::string_view name_view(source); \ - std::from_chars(name_view.data(), name_view.data() + name_view.size(), name); \ - } - static JSONLogger logger; +/** + * Fast parser which converts a string to a value of the desired type. + * + * @param view String to parse. + * @param otherwise Value to return if parsing fails. + * + * @return Value obtained after parsing. + */ +template +T from_chars(std::string_view view, T otherwise){ + T result = otherwise; + std::from_chars(view.data(), view.data() + view.size(), result); + return result; +} + /** * Represent an amount of time. */ @@ -764,15 +772,15 @@ int main_internal(int const argc, char const* argv[]) .detach(); std::string_view last_command(argv[1]); - FROM_CHARS(int, exit_code, 1, argv[2]); + int exit_code = from_chars(argv[2], 1); double begin_ts = std::strtod(argv[3], nullptr); double end_ts = std::strtod(argv[4], nullptr); double delay = end_ts - begin_ts; - FROM_CHARS(std::size_t, columns, 79, argv[5]); + std::size_t columns = from_chars(argv[5], 79); report_command_status(last_command, exit_code, delay, columns); std::string_view pwd(argv[6]); - FROM_CHARS(int, shlvl, 1, argv[7]); + int shlvl = from_chars(argv[7], 1); std::string_view venv_view; char const* venv; if ((venv = getenv("VIRTUAL_ENV_PROMPT")) != nullptr) From 7fcf31841288207c847fc8b62d6a880d4835cfb0 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 28 Jun 2026 22:40:31 +0530 Subject: [PATCH 06/10] Formatted --- custom-prompt/custom-prompt.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index d1ccdc25..5f2cdc92 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -106,8 +106,8 @@ static JSONLogger logger; * * @return Value obtained after parsing. */ -template -T from_chars(std::string_view view, T otherwise){ +template T from_chars(std::string_view view, T otherwise) +{ T result = otherwise; std::from_chars(view.data(), view.data() + view.size(), result); return result; From b62237122894ae3cfec1cdfe70886b802c21b241 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 28 Jun 2026 22:45:46 +0530 Subject: [PATCH 07/10] Rename --- custom-prompt/custom-prompt.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 5f2cdc92..25a2c713 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -106,7 +106,7 @@ static JSONLogger logger; * * @return Value obtained after parsing. */ -template T from_chars(std::string_view view, T otherwise) +template T parse_string_to_integer(std::string_view view, T otherwise) { T result = otherwise; std::from_chars(view.data(), view.data() + view.size(), result); @@ -772,15 +772,15 @@ int main_internal(int const argc, char const* argv[]) .detach(); std::string_view last_command(argv[1]); - int exit_code = from_chars(argv[2], 1); + int exit_code = parse_string_to_integer(argv[2], 1); double begin_ts = std::strtod(argv[3], nullptr); double end_ts = std::strtod(argv[4], nullptr); double delay = end_ts - begin_ts; - std::size_t columns = from_chars(argv[5], 79); + std::size_t columns = parse_string_to_integer(argv[5], 79); report_command_status(last_command, exit_code, delay, columns); std::string_view pwd(argv[6]); - int shlvl = from_chars(argv[7], 1); + int shlvl = parse_string_to_integer(argv[7], 1); std::string_view venv_view; char const* venv; if ((venv = getenv("VIRTUAL_ENV_PROMPT")) != nullptr) From 806750e9142850990558fd767816a80e50b7b3c8 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 28 Jun 2026 22:47:12 +0530 Subject: [PATCH 08/10] Documentation --- custom-prompt/custom-prompt.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 25a2c713..aad3f4a6 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -99,12 +99,12 @@ namespace C static JSONLogger logger; /** - * Fast parser which converts a string to a value of the desired type. + * Fast parser which converts a string to an integer. * * @param view String to parse. - * @param otherwise Value to return if parsing fails. + * @param otherwise Fallback integer to return if parsing fails. * - * @return Value obtained after parsing. + * @return The resultant integer if parsing succeeds, else the fallback. */ template T parse_string_to_integer(std::string_view view, T otherwise) { From 81bb94d6fb8f6d360398daeb3f0fdc33c4b545e9 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 28 Jun 2026 22:52:48 +0530 Subject: [PATCH 09/10] Documentation --- custom-prompt/custom-prompt.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index aad3f4a6..8b37b3a5 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -99,7 +99,9 @@ namespace C static JSONLogger logger; /** - * Fast parser which converts a string to an integer. + * Fast parser which converts (the prefix of) a string to an integer. (With + * some compilers, this may work for floating-point numbers as well, but this + * is not guaranteed.) * * @param view String to parse. * @param otherwise Fallback integer to return if parsing fails. From 3af47b0a8a93914c476d279a57a39d344169a45b Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 28 Jun 2026 23:10:55 +0530 Subject: [PATCH 10/10] Comments --- custom-prompt/custom-prompt.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 8b37b3a5..955ae4fd 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -99,16 +99,14 @@ namespace C static JSONLogger logger; /** - * Fast parser which converts (the prefix of) a string to an integer. (With - * some compilers, this may work for floating-point numbers as well, but this - * is not guaranteed.) + * Try to convert a string to an integer. * * @param view String to parse. * @param otherwise Fallback integer to return if parsing fails. * - * @return The resultant integer if parsing succeeds, else the fallback. + * @return The parsed integer or the fallback. */ -template T parse_string_to_integer(std::string_view view, T otherwise) +template T try_parse_number(std::string_view view, T otherwise) { T result = otherwise; std::from_chars(view.data(), view.data() + view.size(), result); @@ -774,15 +772,17 @@ int main_internal(int const argc, char const* argv[]) .detach(); std::string_view last_command(argv[1]); - int exit_code = parse_string_to_integer(argv[2], 1); + int exit_code = try_parse_number(argv[2], 1); + // Support for parsing floating-point numbers is not consistent across + // standard library implementations, so use a different function. double begin_ts = std::strtod(argv[3], nullptr); double end_ts = std::strtod(argv[4], nullptr); double delay = end_ts - begin_ts; - std::size_t columns = parse_string_to_integer(argv[5], 79); + std::size_t columns = try_parse_number(argv[5], 79); report_command_status(last_command, exit_code, delay, columns); std::string_view pwd(argv[6]); - int shlvl = parse_string_to_integer(argv[7], 1); + int shlvl = try_parse_number(argv[7], 1); std::string_view venv_view; char const* venv; if ((venv = getenv("VIRTUAL_ENV_PROMPT")) != nullptr)