mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-21 15:19:11 +08:00
Replace ScopedPush with scoped_push which is underpinned by ScopeGuard
This allows us to use the scoped push in more scenarios by appeasing the borrow checker. Use it in a couple of places instead of ScopeGuard. Hopefully this is makes porting easier.
This commit is contained in:
parent
2d4fbc290b
commit
a5cae59082
@ -1855,38 +1855,44 @@ impl<T, F: FnOnce(&mut T), C> Drop for ScopeGuard<T, F, C> {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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. Note that this can only be
|
||||
/// used if the code does not access the captured variable again for the duration of the scope. If
|
||||
/// that's not the case (the code will refuse to compile), use a [`ScopeGuard`] instance instead.
|
||||
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),
|
||||
}
|
||||
/// A scoped manager to save the current value of some variable, and set it to a new value. When
|
||||
/// dropped, it restores the variable to its old value.
|
||||
#[allow(clippy::type_complexity)] // Not sure how to extract the return type.
|
||||
pub fn scoped_push<Context, Accessor, T>(
|
||||
mut ctx: Context,
|
||||
accessor: Accessor,
|
||||
new_value: T,
|
||||
) -> ScopeGuard<(Context, Accessor, T), fn(&mut (Context, Accessor, T)), Context>
|
||||
where
|
||||
Accessor: Fn(&mut Context) -> &mut T,
|
||||
T: Copy,
|
||||
{
|
||||
fn restore_saved_value<Context, Accessor, T: Copy>(data: &mut (Context, Accessor, T))
|
||||
where
|
||||
Accessor: Fn(&mut Context) -> &mut T,
|
||||
{
|
||||
let (ref mut ctx, ref accessor, saved_value) = data;
|
||||
*accessor(ctx) = *saved_value;
|
||||
}
|
||||
|
||||
pub fn restore(&mut self) {
|
||||
if let Some(saved_value) = self.saved_value.take() {
|
||||
*self.var = saved_value;
|
||||
}
|
||||
fn view_context<Context, Accessor, T>(data: &(Context, Accessor, T)) -> &Context
|
||||
where
|
||||
Accessor: Fn(&mut Context) -> &mut T,
|
||||
{
|
||||
&data.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Drop for ScopedPush<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
self.restore()
|
||||
fn view_context_mut<Context, Accessor, T>(data: &mut (Context, Accessor, T)) -> &mut Context
|
||||
where
|
||||
Accessor: Fn(&mut Context) -> &mut T,
|
||||
{
|
||||
&mut data.0
|
||||
}
|
||||
let saved_value = mem::replace(accessor(&mut ctx), new_value);
|
||||
ScopeGuard::with_view(
|
||||
(ctx, accessor, saved_value),
|
||||
view_context,
|
||||
view_context_mut,
|
||||
restore_saved_value,
|
||||
)
|
||||
}
|
||||
|
||||
pub const fn assert_send<T: Send>() {}
|
||||
|
@ -13,7 +13,7 @@ use std::sync::{Arc, Mutex};
|
||||
use widestring_suffix::widestrs;
|
||||
|
||||
use crate::builtins::shared::io_streams_t;
|
||||
use crate::common::{escape_string, replace_with, EscapeFlags, EscapeStringStyle, ScopeGuard};
|
||||
use crate::common::{escape_string, scoped_push, EscapeFlags, EscapeStringStyle, ScopeGuard};
|
||||
use crate::ffi::{self, block_t, parser_t, signal_check_cancel, signal_handle, Repin};
|
||||
use crate::flog::FLOG;
|
||||
use crate::signal::Signal;
|
||||
@ -676,13 +676,17 @@ fn fire_internal(parser: &mut parser_t, event: &Event) {
|
||||
);
|
||||
|
||||
// Suppress fish_trace during events.
|
||||
let saved_is_event = replace_with(&mut parser.libdata_pod().is_event, |old| old + 1);
|
||||
let saved_suppress_fish_trace =
|
||||
std::mem::replace(&mut parser.libdata_pod().suppress_fish_trace, true);
|
||||
let mut parser = ScopeGuard::new(parser, |parser| {
|
||||
parser.libdata_pod().is_event = saved_is_event;
|
||||
parser.libdata_pod().suppress_fish_trace = saved_suppress_fish_trace;
|
||||
});
|
||||
let is_event = parser.libdata_pod().is_event;
|
||||
let mut parser = scoped_push(
|
||||
parser,
|
||||
|parser| &mut parser.libdata_pod().is_event,
|
||||
is_event + 1,
|
||||
);
|
||||
let mut parser = scoped_push(
|
||||
&mut *parser,
|
||||
|parser| &mut parser.libdata_pod().suppress_fish_trace,
|
||||
true,
|
||||
);
|
||||
|
||||
// Capture the event handlers that match this event.
|
||||
let fire: Vec<_> = EVENT_HANDLERS
|
||||
@ -717,7 +721,7 @@ fn fire_internal(parser: &mut parser_t, event: &Event) {
|
||||
let saved_is_interactive =
|
||||
std::mem::replace(&mut parser.libdata_pod().is_interactive, false);
|
||||
let saved_statuses = parser.get_last_statuses().within_unique_ptr();
|
||||
let mut parser = ScopeGuard::new(&mut parser, |parser| {
|
||||
let mut parser = ScopeGuard::new(&mut *parser, |parser| {
|
||||
parser.pin().set_last_statuses(saved_statuses);
|
||||
parser.libdata_pod().is_interactive = saved_is_interactive;
|
||||
});
|
||||
@ -731,14 +735,14 @@ fn fire_internal(parser: &mut parser_t, event: &Event) {
|
||||
"'"
|
||||
);
|
||||
|
||||
let b = parser
|
||||
let b = (*parser)
|
||||
.pin()
|
||||
.push_block(block_t::event_block((event as *const Event).cast()).within_unique_ptr());
|
||||
parser
|
||||
(*parser)
|
||||
.pin()
|
||||
.eval_string_ffi1(&buffer.to_ffi())
|
||||
.within_unique_ptr();
|
||||
parser.pin().pop_block(b);
|
||||
(*parser).pin().pop_block(b);
|
||||
|
||||
handler.fired.store(true, Ordering::Relaxed);
|
||||
fired_one_shot |= handler.is_one_shot();
|
||||
|
Loading…
x
Reference in New Issue
Block a user