fish-shell/fish-rust/src/common.rs
Mahmoud Al-Qudsi 05265e7d90 Port (and use) ASSERT_IS_BACKGROUND_THREAD/ASSERT_IS_MAIN_THREAD
Rust doesn't have __FUNCTION__ or __func__ (though you can hack around it with a
proc macro, but that will require a separate crate and slowing down compilation
times with heavy proc macro dependencies), so these are just regular functions
(at least for now). Rust's default stack trace on panic (even in release mode)
should be enough (and the functions themselves are inlined so the calling
function should be the second frame from the top, after the #[cold] panic
functions).
2023-02-19 16:54:50 -06:00

93 lines
2.9 KiB
Rust

use crate::ffi;
use crate::wchar_ffi::{wstr, WCharFromFFI, WString};
use std::ffi::c_uint;
use std::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.
///
/// This can be handy when there are multiple code paths to exit a block.
pub struct ScopedPush<'a, T> {
var: &'a mut T,
saved_value: Option<T>,
}
impl<'a, T> ScopedPush<'a, T> {
pub fn new(var: &'a mut T, new_value: T) -> Self {
let saved_value = mem::replace(var, new_value);
Self {
var,
saved_value: Some(saved_value),
}
}
pub fn restore(&mut self) {
if let Some(saved_value) = self.saved_value.take() {
*self.var = saved_value;
}
}
}
impl<'a, T> Drop for ScopedPush<'a, T> {
fn drop(&mut self) {
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()
}