Struct duat_core::commands::Commands

source ·
pub struct Commands<U>
where U: Ui,
{ /* private fields */ }
Expand description

A list of [Command]s.

This list contains all of the [Command]s that have been added to Duat, as well as info on the current File, widget and all of the windows.

Implementations§

source§

impl<U> Commands<U>
where U: Ui,

source

pub const fn new( current_file: &'static CurFile<U>, current_widget: &'static CurWidget<U>, ) -> Self

Returns a new instance of Commands.

source

pub fn quit(&self)

Canonical way to quit Duat.

By calling the quit command, all threads will finish their tasks, and then Duat will execute a program closing function, as defined by the Ui.

source

pub fn switch_to<W: ActiveWidget<U>>(&self) -> Result<Option<Text>, ()>

Switches to the given ActiveWidget.

The widget will be chosen in the following order:

  1. The first of said widget pushed to the current File.
  2. Other instances of it in the current window.
  3. Instances in other windows.
source

pub fn edit(&self, file: impl Display) -> Result<Option<Text>, ()>

Switches to/opens a File with the given name.

If you wish to specifically switch to files that are already open, use Commands::buffer.

If there are more arguments, they will be ignored.

source

pub fn buffer(&self, file: impl Display) -> Result<Option<Text>, ()>

Switches to a File with the given name.

If there is no file open with that name, does nothing. Use Commands::edit if you wish to open files.

If there are more arguments, they will be ignored.

source

pub fn next_file(&self) -> Result<Option<Text>, ()>

Switches to the next File.

This function will only look at files that are opened in the current window. If you want to include other windows in the search, use Commands::next_global_file.

source

pub fn prev_file(&self) -> Result<Option<Text>, ()>

Switches to the previous File.

This function will only look at files that are opened in the current window. If you want to include other windows in the search, use Commands::prev_global_file.

source

pub fn next_global_file(&self) -> Result<Option<Text>, ()>

Switches to the next File.

This function will look for files in all windows. If you want to limit the search to just the current window, use Commands::next_file.

source

pub fn prev_global_file(&self) -> Result<Option<Text>, ()>

Switches to the previous File.

This function will look for files in all windows. If you want to limit the search to just the current window, use Commands::prev_file.

source

pub fn return_to_file(&self) -> Result<Option<Text>, ()>

If not in a File, switches to the last active File.

This is useful if the currently active widget is not a file (e.g. CommandLine, a file tree, etc), and you want to return to the file seamlessly.

source

pub fn alias( &self, alias: impl ToString, command: impl ToString, ) -> Result<Option<Text>, ()>

Tries to alias a caller to an existing command.

Returns an Err if the caller is already a caller for another command, or if command is not a real caller to an exisiting [Command].

source

pub fn run(&self, call: impl Display) -> Result<Option<Text>, ()>

Runs a full command, with a caller, Flags, and Args.

When running the command, the ordering of flags does not matter, as long as they are placed before the arguments to the command.

§Examples
context.commands.run("set-prompt new-prompt")

In this case we’re running a command that will affect the most relevant CommandLine. See Commands::add_for_widget for more information.

source

pub fn add( &self, callers: impl IntoIterator<Item = impl ToString>, f: impl FnMut(Flags<'_, '_>, Args<'_>) -> CmdResult + 'static, ) -> Result<(), ()>

Adds a command to the global list of commands.

This command cannot take any arguments beyond the Flags and Args, so any mutation of state must be done through captured variables, usually in the form of RwDatas.

§Examples
// Shared state, which will be displayed in a `StatusLine`.
let var = RwData::new(35);

/* inside of a plugin, where a `Context` could be found */
context.commands.add(["set-var"], {
    let var = var.clone();
    move |_flags, mut args| {
        let value: usize = args.next_as()?;
        *var.write() = value;

        Ok(None)
    }
});
/* */

let status_cfg = status!("The value is currently " var);

Since var is an RwData, it will be updated automatically in the StatusLine

source

pub fn add_for_current<T: 'static>( &'static self, callers: impl IntoIterator<Item = impl ToString>, f: impl FnMut(&mut T, Flags<'_, '_>, Args<'_>) -> CmdResult + 'static, ) -> Result<(), ()>

Adds a command to an object “related” to the current File

This object can be one of three things, a PassiveWidget, an InputMethod, or the File itself. When the command is ran, Duat will look at the currently active file for any instance of an RwData<Thing> it can find. Those will either be the file itself, or will be added in the Session’s “file_fn”.

§Examples
#[derive(Debug)]
enum Mode {
    Normal,
    Insert,
    Prompt,
    Visual,
}

struct ModalEditor {
    mode: Mode,
}

impl InputMethod for ModalEditor {
    /* Implementation details. */
}

context.commands.add_for_current::<ModalEditor>(
    ["set-mode"],
    |modal, flags, mut args| {
        let mode = args.next_else(text!("No mode given"))?;

        match mode {
            "normal" | "Normal" => modal.mode = Mode::Normal,
            "insert" | "Insert" => modal.mode = Mode::Insert,
            "prompt" | "Prompt" => modal.mode = Mode::Prompt,
            "visual" | "Visual" => modal.mode = Mode::Visual,
            mode => {
                return Err(text!(
                    "Mode" [AccentErr] mode []
                    "is not a valid mode"
                ));
            }
        }

        let mode = format!("{:?}", modal.mode);
        Ok(Some(text!("Mode was set to " [AccentOk] mode [] ".")))
    }
)
.unwrap();
source

pub fn add_for_widget<W: PassiveWidget<U>>( &'static self, callers: impl IntoIterator<Item = impl ToString>, f: impl FnMut(&mut W, &U::Area, Flags<'_, '_>, Args<'_>) -> CmdResult + 'static, ) -> Result<(), ()>

Adds a command that can mutate a widget of the given type, along with its associated dyn Area.

This command will look for the PassiveWidget in the following order:

  1. Any instance that is “related” to the currently active File, that is, any widgets that were added during the Session’s “file_fn”.
  2. Other widgets in the currently active window, related or not to any given File.
  3. Any instance of the PassiveWidget that is found in other windows, looking first at windows ahead.

Keep in mind that the search is deterministic, that is, if there are multiple instances of the widget that fit the same category, only one of them will ever be used.

This search algorithm allows a more versatile configuration of widgets, for example, one may have a CommandLine per File, or one singular CommandLine that acts upon all files in the window, and both would respond correctly to the "set-prompt" command.

§Examples

In this example, we create a simple Timer widget, along with some control commands.

// Required feature for widgets.
#![feature(return_position_impl_trait_in_trait)]
impl PassiveWidget for Timer {
    fn build<U: Ui>() -> (Widget<U>, impl Fn() -> bool, PushSpecs) {
        let timer = Self {
            text: text!(AlignCenter [Counter] "0ms"),
            instant: Instant::now(),
            // No need to use an `RwData`, since
            // `RwData::has_changed` is never called.
            running: Arc::new(AtomicBool::new(false)),
        };

        // The checker should tell the `Timer` to update only
        // if `running` is `true`.
        let checker = {
            // Clone any variables before moving them to
            // the `checker`.
            let running = timer.running.clone();
            move || running.load(Ordering::Relaxed)
        };

        let specs = PushSpecs::below().with_lenght(1.0);

        (Widget::passive(timer), checker, specs)
    }

    fn update(&mut self, _area: &impl Area) {
        if self.running.load(Ordering::Relaxed) {
            let duration = self.instant.elapsed();
            let duration = format!("{:.3?}", duration);
            self.text = text!(
                AlignCenter [Counter] duration [] "elapsed"
            );
        }
    }
     

    fn text(&self) -> &Text {
        &self.text
    }

    // The `once` function of a `PassiveWidget` is only called
    // when that widget is first created.
    // It is generally useful to add commands and set forms
    // in the `palette`.
    fn once() {
        // `palette::set_weak_form` will only set that form if
        // it doesn't already exist.
        // That means that a user of the widget will be able to
        // control that form by changing it before or after this
        // widget is pushed.
        palette::set_weak_form("Counter", Form::new().green());

        commands::add_for_widget::<Timer>(
            ["play"],
            |timer, _area, _flags, _args| {
                timer.running.store(true, Ordering::Relaxed);

                Ok(None)
            })
            .unwrap();

        commands::add_for_widget::<Timer>(
            ["pause"],
            |timer, _area, _flags, _args| {
                timer.running.store(false, Ordering::Relaxed);

                Ok(None)
            })
            .unwrap();

        commands::add_for_widget::<Timer>(
            ["pause"],
            |timer, _area, _flags, _args| {
                timer.instant = Instant::now();

                Ok(None)
            })
            .unwrap();
    }
}

Auto Trait Implementations§

§

impl<U> !Freeze for Commands<U>

§

impl<U> !RefUnwindSafe for Commands<U>

§

impl<U> Send for Commands<U>

§

impl<U> Sync for Commands<U>

§

impl<U> Unpin for Commands<U>

§

impl<U> !UnwindSafe for Commands<U>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.