Skip to main content

BulkModal

Struct BulkModal 

Source
pub struct BulkModal {
    pub action: BatchAction,
    pub flags: PatchFlags,
    pub target: Option<String>,
    pub kind: Option<String>,
    pub cursor: usize,
    pub focus: BulkFocus,
    pub draft: String,
    pub selection: BulkSelection,
    pub state: BulkState,
    pub note: Option<String>,
    pub plan_stale: bool,
}
Expand description

The batch modal.

Fields§

§action: BatchAction§flags: PatchFlags

The CLI’s flag struct, not a locally built patch (see the module docs).

§target: Option<String>

The other end of a pair.

§kind: Option<String>

The relationship kind, as the user will set it.

§cursor: usize

Which row the cursor is on.

§focus: BulkFocus§draft: String

The text being typed, while focus is BulkFocus::Edit.

A draft is discarded on esc, never committed. An earlier draft of this modal snapshotted the row on begin_edit and restored it on esc; the snapshot was dead — commit_edit is the only thing that writes a row, so the restore and a clear were indistinguishable from outside. The revert-and-red run is what proved it: a mutation replacing the restore with a clear left all 141 cases green.

§selection: BulkSelection§state: BulkState§note: Option<String>

The last message, for the status bar.

§plan_stale: bool

Whether the plan no longer matches the screen.

Set on the first preview and on any change to the selection or the flags, so a confirm can never apply a plan the user has not looked at.

Implementations§

Source§

impl BulkModal

Source

pub fn new(action: BatchAction) -> Self

A fresh modal for action.

Source

pub fn row_names(&self) -> Vec<&'static str>

The row names, in the order tab walks them.

Depends on the action, and that is the point: an archive has no rows, because ArchiveRequest::archive() names no target status and inventing a field for one would be offering a restore that #190’s C-003 does not allow. A pair has no field rows either — it has a target and a kind.

Source

pub fn row_name(&self, index: usize) -> &'static str

The name of the row at index, for the render.

Source

pub fn row_value(&self, index: usize) -> String

The value of the row at index.

An absent value is the em dash, not an empty string, so a blank row is visibly blank rather than looking like a field set to "". The distinction is the whole WP06 finding: a blank --estimate "" is Unchanged.

Source

pub fn set_row(&mut self, index: usize, value: String) -> Result<()>

Store value on the row at index, or say why it cannot be stored.

A blank value is stored as absent (None), which is what makes “the user cleared the field” and “the user never touched it” the same request — the contract’s Unchanged. The clear row is the explicit way to empty something, and it is the only row that may name a field clear does not own.

Source

pub fn mark_stale(&mut self)

Mark that the plan no longer matches the screen.

contracts/patch-plan.md §4: “Apply requires the exact confirmed plan … any change to selection or patch requires a new preview.” So a confirm is refused while stale, and the refusal says why rather than silently re-previewing — a silent re-preview would apply something the user did not look at.

Source

pub fn begin_edit(&mut self)

Begin editing the row under the cursor.

Source

pub fn commit_edit(&mut self) -> Result<()>

Commit the draft, or report why it cannot be committed.

Source

pub fn abort_edit(&mut self)

Abandon the draft. The row keeps whatever it had.

Discarding rather than committing is the point: an abandoned edit that still wrote the half-typed value is an abandoned edit that changed state. The draft is thrown away rather than left in place, because begin_edit rebuilds it from the row every time — so a leftover draft is a draft nothing can read.

Source

pub fn move_cursor(&mut self, delta: isize)

Move the cursor, wrapping. A no-op when the action has no rows (an archive).

Source

pub fn patch(&self) -> Result<IssuePatch>

The typed patch for a field action, or say why it cannot be built.

Delegates to the CLI’s own conversion, so a TUI field and a CLI flag mean the same thing — including the “a blank field is Unchanged, not Clear” rule WP06 found. A TUI that built its own patch would have its own blank rule.

Source

pub fn patch_for(&self) -> Result<IssuePatch>

The typed patch for this action, or say why it cannot be built.

One method, because the preview and the confirm both need it, and two match self.action blocks are two places for an action to be handled differently.

Source

pub fn preview(&mut self, store: &Store, issues: &[(u32, Issue)]) -> Result<()>

Build a plan for the current selection. Read-only by construction: it resolves, validates and renders a preview, and writes nothing.

Source

pub fn relationship_for( &self, numbers: &[u32], kind_override: Option<String>, ) -> Result<RelationshipOp>

The relationship operation for numbers, or the field the user has not filled in.

A pair’s from is per selected issue, not the whole selection: from is a single issue in the relationship vocabulary, and the batch is the set of edges. Passing the whole selection as from would build a plan for an edge that does not exist.

Source

pub fn archive_request(&self) -> ArchiveRequest

The archive request.

The TUI’s archive action is archive only — there is no restore verb on this modal, because a restore needs an explicit target status (#190’s C-003) and there is no row for one. A modal that offered a restore with no target would be offering the request #190 rejects.

Source

pub fn arm(&mut self)

Go from a shown plan to the confirming state.

Two steps rather than one, because “I saw it” and “I approved it” are two different decisions and a single y conflates them. The confirming state renders a different affordance, so the user can see which one they are in.

Source

pub fn is_armed(&self) -> bool

Whether the modal is armed — the state in which y writes.

Source

pub fn confirm(&mut self, store: &Store) -> Result<()>

Confirm the plan that is on screen and apply it.

Refuses while the plan is stale, and the refusal says why. That is contract §4’s “any change to selection or patch requires a new preview”, and it is checked here rather than inside the apply so a TUI user gets a TUI message.

Source

pub fn cancel(&mut self)

Back to choosing, from any state.

confirm is the only method here that writes, so cancelling from any other state cannot have changed a file. The confirm state keeps its plan so a mis-aimed esc does not throw away a preview the user wanted to look at again.

Source

pub fn state_label(&self) -> &'static str

The state, in the words a user reads.

Source

pub fn rows(&self) -> Vec<(bool, String, String)>

The rows, as the modal shows them: a cursor, a name and a value.

Source

pub fn footer(&self) -> String

The footer, naming the keys that mean something right now.

The list is per-focus and per-state, because a footer that names y while y types a letter is a footer that teaches the wrong thing.

Source

pub fn body(&self) -> String

The text a surface shows for the current state, from the CLI’s renderers.

Trait Implementations§

Source§

impl Clone for BulkModal

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for BulkModal

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

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

Source§

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.