From e6e866e455dfaeecb0f607fdf01b13f1bcf4c291 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sat, 11 Feb 2023 16:51:43 +0100 Subject: [PATCH] Port escape_string() to Rust --- fish-rust/src/common.rs | 63 ++++++++++++++++++++++++++++++++++++++++- fish-rust/src/ffi.rs | 2 ++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/fish-rust/src/common.rs b/fish-rust/src/common.rs index e5942ba2a..3042ad9cb 100644 --- a/fish-rust/src/common.rs +++ b/fish-rust/src/common.rs @@ -1,4 +1,8 @@ -use std::mem; +use crate::{ + ffi, + wchar_ffi::{wstr, WCharFromFFI, WString}, +}; +use std::{ffi::c_uint, mem}; /// A scoped manager to save the current value of some variable, and optionally set it to a new /// value. When dropped, it restores the variable to its old value. @@ -31,3 +35,60 @@ impl<'a, T> Drop for ScopedPush<'a, T> { self.restore() } } + +pub enum EscapeStringStyle { + Script(EscapeFlags), + Url, + Var, + Regex, +} + +/// Flags for the [`escape_string()`] function. These are only applicable when the escape style is +/// [`EscapeStringStyle::Script`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub struct EscapeFlags { + /// Do not escape special fish syntax characters like the semicolon. Only escape non-printable + /// characters and backslashes. + pub no_printables: bool, + /// Do not try to use 'simplified' quoted escapes, and do not use empty quotes as the empty + /// string. + pub no_quoted: bool, + /// Do not escape tildes. + pub no_tilde: bool, + /// Replace non-printable control characters with Unicode symbols. + pub symbolic: bool, +} + +/// Replace special characters with backslash escape sequences. Newline is replaced with `\n`, etc. +pub fn escape_string(s: &wstr, style: EscapeStringStyle) -> WString { + let mut flags_int = 0; + + let style = match style { + EscapeStringStyle::Script(flags) => { + const ESCAPE_NO_PRINTABLES: c_uint = 1 << 0; + const ESCAPE_NO_QUOTED: c_uint = 1 << 1; + const ESCAPE_NO_TILDE: c_uint = 1 << 2; + const ESCAPE_SYMBOLIC: c_uint = 1 << 3; + + if flags.no_printables { + flags_int |= ESCAPE_NO_PRINTABLES; + } + if flags.no_quoted { + flags_int |= ESCAPE_NO_QUOTED; + } + if flags.no_tilde { + flags_int |= ESCAPE_NO_TILDE; + } + if flags.symbolic { + flags_int |= ESCAPE_SYMBOLIC; + } + + ffi::escape_string_style_t::STRING_STYLE_SCRIPT + } + EscapeStringStyle::Url => ffi::escape_string_style_t::STRING_STYLE_URL, + EscapeStringStyle::Var => ffi::escape_string_style_t::STRING_STYLE_VAR, + EscapeStringStyle::Regex => ffi::escape_string_style_t::STRING_STYLE_REGEX, + }; + + ffi::escape_string(s.as_ptr(), flags_int.into(), style).from_ffi() +} diff --git a/fish-rust/src/ffi.rs b/fish-rust/src/ffi.rs index 087841b50..de94e3b21 100644 --- a/fish-rust/src/ffi.rs +++ b/fish-rust/src/ffi.rs @@ -68,6 +68,8 @@ include_cpp! { generate!("wait_handle_store_t") generate!("event_fire_generic") + + generate!("escape_string") } impl parser_t {