mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-22 15:16:24 +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
|
/// A scoped manager to save the current value of some variable, and set it to a new value. When
|
||||||
/// value. When dropped, it restores the variable to its old value.
|
/// dropped, it restores the variable to its old value.
|
||||||
///
|
#[allow(clippy::type_complexity)] // Not sure how to extract the return type.
|
||||||
/// This can be handy when there are multiple code paths to exit a block. Note that this can only be
|
pub fn scoped_push<Context, Accessor, T>(
|
||||||
/// used if the code does not access the captured variable again for the duration of the scope. If
|
mut ctx: Context,
|
||||||
/// that's not the case (the code will refuse to compile), use a [`ScopeGuard`] instance instead.
|
accessor: Accessor,
|
||||||
pub struct ScopedPush<'a, T> {
|
new_value: T,
|
||||||
var: &'a mut T,
|
) -> ScopeGuard<(Context, Accessor, T), fn(&mut (Context, Accessor, T)), Context>
|
||||||
saved_value: Option<T>,
|
where
|
||||||
}
|
Accessor: Fn(&mut Context) -> &mut T,
|
||||||
|
T: Copy,
|
||||||
impl<'a, T> ScopedPush<'a, T> {
|
{
|
||||||
pub fn new(var: &'a mut T, new_value: T) -> Self {
|
fn restore_saved_value<Context, Accessor, T: Copy>(data: &mut (Context, Accessor, T))
|
||||||
let saved_value = mem::replace(var, new_value);
|
where
|
||||||
|
Accessor: Fn(&mut Context) -> &mut T,
|
||||||
Self {
|
{
|
||||||
var,
|
let (ref mut ctx, ref accessor, saved_value) = data;
|
||||||
saved_value: Some(saved_value),
|
*accessor(ctx) = *saved_value;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
fn view_context<Context, Accessor, T>(data: &(Context, Accessor, T)) -> &Context
|
||||||
pub fn restore(&mut self) {
|
where
|
||||||
if let Some(saved_value) = self.saved_value.take() {
|
Accessor: Fn(&mut Context) -> &mut T,
|
||||||
*self.var = saved_value;
|
{
|
||||||
}
|
&data.0
|
||||||
}
|
}
|
||||||
}
|
fn view_context_mut<Context, Accessor, T>(data: &mut (Context, Accessor, T)) -> &mut Context
|
||||||
|
where
|
||||||
impl<'a, T> Drop for ScopedPush<'a, T> {
|
Accessor: Fn(&mut Context) -> &mut T,
|
||||||
fn drop(&mut self) {
|
{
|
||||||
self.restore()
|
&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>() {}
|
pub const fn assert_send<T: Send>() {}
|
||||||
|
@ -13,7 +13,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
use widestring_suffix::widestrs;
|
use widestring_suffix::widestrs;
|
||||||
|
|
||||||
use crate::builtins::shared::io_streams_t;
|
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::ffi::{self, block_t, parser_t, signal_check_cancel, signal_handle, Repin};
|
||||||
use crate::flog::FLOG;
|
use crate::flog::FLOG;
|
||||||
use crate::signal::Signal;
|
use crate::signal::Signal;
|
||||||
@ -676,13 +676,17 @@ fn fire_internal(parser: &mut parser_t, event: &Event) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Suppress fish_trace during events.
|
// Suppress fish_trace during events.
|
||||||
let saved_is_event = replace_with(&mut parser.libdata_pod().is_event, |old| old + 1);
|
let is_event = parser.libdata_pod().is_event;
|
||||||
let saved_suppress_fish_trace =
|
let mut parser = scoped_push(
|
||||||
std::mem::replace(&mut parser.libdata_pod().suppress_fish_trace, true);
|
parser,
|
||||||
let mut parser = ScopeGuard::new(parser, |parser| {
|
|parser| &mut parser.libdata_pod().is_event,
|
||||||
parser.libdata_pod().is_event = saved_is_event;
|
is_event + 1,
|
||||||
parser.libdata_pod().suppress_fish_trace = saved_suppress_fish_trace;
|
);
|
||||||
});
|
let mut parser = scoped_push(
|
||||||
|
&mut *parser,
|
||||||
|
|parser| &mut parser.libdata_pod().suppress_fish_trace,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
// Capture the event handlers that match this event.
|
// Capture the event handlers that match this event.
|
||||||
let fire: Vec<_> = EVENT_HANDLERS
|
let fire: Vec<_> = EVENT_HANDLERS
|
||||||
@ -717,7 +721,7 @@ fn fire_internal(parser: &mut parser_t, event: &Event) {
|
|||||||
let saved_is_interactive =
|
let saved_is_interactive =
|
||||||
std::mem::replace(&mut parser.libdata_pod().is_interactive, false);
|
std::mem::replace(&mut parser.libdata_pod().is_interactive, false);
|
||||||
let saved_statuses = parser.get_last_statuses().within_unique_ptr();
|
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.pin().set_last_statuses(saved_statuses);
|
||||||
parser.libdata_pod().is_interactive = saved_is_interactive;
|
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()
|
.pin()
|
||||||
.push_block(block_t::event_block((event as *const Event).cast()).within_unique_ptr());
|
.push_block(block_t::event_block((event as *const Event).cast()).within_unique_ptr());
|
||||||
parser
|
(*parser)
|
||||||
.pin()
|
.pin()
|
||||||
.eval_string_ffi1(&buffer.to_ffi())
|
.eval_string_ffi1(&buffer.to_ffi())
|
||||||
.within_unique_ptr();
|
.within_unique_ptr();
|
||||||
parser.pin().pop_block(b);
|
(*parser).pin().pop_block(b);
|
||||||
|
|
||||||
handler.fired.store(true, Ordering::Relaxed);
|
handler.fired.store(true, Ordering::Relaxed);
|
||||||
fired_one_shot |= handler.is_one_shot();
|
fired_one_shot |= handler.is_one_shot();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user