Skip to main content

FormState

Struct FormState 

Source
pub struct FormState {
Show 20 fields pub title: String, pub status: String, pub priority: String, pub labels: String, pub assignee: String, pub estimate: String, pub cycles: String, pub milestones: String, pub reviewer: String, pub start_date: String, pub due_date: String, pub parent: String, pub target: NewIssueTarget, pub template: String, pub template_scope: Option<String>, pub body: String, pub projects: String, pub epics: String, pub focus: FormFocus, pub cursor: usize,
}

Fields§

§title: String§status: String§priority: String§labels: String§assignee: String§estimate: String§cycles: String§milestones: String§reviewer: String§start_date: String§due_date: String§parent: String

The chosen parent’s number, as a string (WP06 / T026).

A String for the same reason assignee is one: the form’s fields are uniformly text, and each is parsed and validated at submit rather than at Empty means no parent, which carries the same meaning as an empty --parent "" on the CLI.

§target: NewIssueTarget

The entry target of the F4 New Issue mode. Choosing a side writes the matching status into Self::status, which is what submit reads.

§template: String

The selected template’s identity, or empty for none.

A stable template ID ([issue_templates.<id>]) when Self::template_scope is set, otherwise the legacy [templates.<name>] record’s name. A label only: the fields it filled are held separately, so clearing the selection keeps what was typed.

The stable-ID case is identity, not a display label (C-002): a rename in tix.toml changes the label the row shows through Self::display_value, never this value — so a submit resolves against the same template after the rename.

§template_scope: Option<String>

The explicit scope of the selected stable template, when one is selected.

Some("repository")/Some("board:<name>")/Some("team:<label>") marks the selection as a stable-ID template and makes the scope visible (FR-005): Self::display_value renders it beside the ID. None means no stable template is selected — either none at all, or a legacy [templates.<name>] pre-fill. The scope is the template’s own declared scope, split out here so it travels with the selection and is what the shared resolver is asked for.

§body: String

The issue body (Markdown). Submitted verbatim; rendered with newlines escaped so the row stays one line.

§projects: String

The issue’s project associations (WP06 T029), as the comma-joined spelling of the resolved project ids — the same shape labels, cycles and milestones use, and the shape the submit path parses.

A set of ids, not a display string: the picker offers crate::projects::list_projects’ ids, Self::from_issue pre-selects the issue’s stored associations so an edit cannot silently drop the ones the user did not touch, and the service validates them at submit. The form itself never constructs or validates a project.

§epics: String

The issue’s epic references (WP06 T031), as the comma-joined spelling of the resolved epic ids — the same shape projects, labels, cycles and milestones use, and the shape the submit path parses.

A set of ids, not a display string: the picker offers crate::epics::list_epics’ ids, Self::from_issue pre-selects the issue’s stored references so an edit or clone cannot silently drop the ones the user did not touch, and the service validates them at submit. The form itself never constructs or validates an epic.

§focus: FormFocus§cursor: usize

The insertion point in the focused field, in characters (not bytes, so a multi-byte value is never split). Always clamped to the field’s value when used; every writer that replaces a value wholesale resets it to the end.

Implementations§

Source§

impl FormState

Source

pub fn new(default_status: &str) -> Self

Source

pub fn with_default_assignee( default_status: &str, default_assignee: &str, ) -> Self

Source

pub fn apply_template(&mut self, name: &str, template: &IssueTemplate)

Pre-fill the rows a template sets, leaving rows it omits untouched.

Untouched rather than cleared is the whole point: a template is applied to a form the user may already have typed into, and a template that named only labels must not silently erase their title. Vector fields follow the same rule as the submit path — they are the comma-joined spelling of the list they would create.

Source

pub fn apply_stable_template( &mut self, id: &str, scope: &str, template: &Template, )

Pre-fill the rows a stable-ID template sets, and record its ID + scope.

The sibling of Self::apply_template for [issue_templates.<id>] records (WP05/T024), and deliberately the same shape: only rows the template actually sets are written, so applying a labels-only template cannot erase a title the user already typed.

The values come from the template’s defaults and its prompt defaults, in the same precedence the shared resolver merges them (contracts/ resolver.md): a prompt’s default wins over the block default for the same key, because user input would. This is seeding only — required prompts with no value are left empty and reported by the resolver at submit, not pre-filled with a placeholder.

template.extensions (unknown metadata) is not read: it is preserved data, never interpreted as a form field (C-006). List-valued defaults are joined with the same comma rule the submit path parses, and rows this form does not have (files, related_issues, type) are applied by the resolver from the defaults at submit instead — the form neither invents a row for them nor silently drops them.

Source

pub fn from_issue(issue: &Issue) -> Self

This form with every field prefilled from an existing issue — the TUI’s “clone issue” action (tix #1484).

Exactly the fields the form has are carried over, which is exactly the fields creation takes: number, created, commit and History are not creation inputs, so they are not carried. The title is copied verbatim rather than suffixed with “copy”: the user asked for the source’s data, a title is not an identity (numbers are), and inventing a naming convention here would put a string in the user’s issue that no command in this tool produces.

Multivalued fields are filled in the same comma-separated form the submit path parses (labels, cycles, milestones), so a clone submitted unchanged round-trips the source’s values exactly.

Source

pub fn value_of(&self, focus: FormFocus) -> &str

This form’s value for focus, regardless of which field is focused.

focused_value is value_of(self.focus). The indirection exists so the renderer can walk FormFocus::RING and read each field in turn, which is what lets one list drive both the labels and the focus index.

Source

pub fn display_value(&self, focus: FormFocus) -> Cow<'_, str>

The text actually drawn for focus.

Identical to Self::value_of everywhere but two rows. The body’s newlines are escaped (\n) so a multi-line Markdown body occupies one row and the row arithmetic the caret depends on stays true; the submitted value keeps the real newlines. The Template row appends the selected template’s explicit scope (id [scope]) so the scope is visible before submit (FR-005); the stored Self::template stays the bare ID, which is what selection and resolution read.

Source

pub fn focused_display_value(&self) -> Cow<'_, str>

Self::display_value for the focused row.

Source

pub fn focused_value(&self) -> &str

Source

pub fn focused_value_mut(&mut self) -> Option<&mut String>

The focused field’s editable buffer, or None when the field has none.

Option rather than a panic for the control rows: Target is an enum with no buffer of its own, and the alternative — a &mut String arm that panics — would make a guard in insert_char the only thing standing between a mis-set focus and an abort. A None makes the callers handle it.

Source

pub fn cursor(&self) -> usize

The insertion point, clamped to the focused value’s length.

Source

pub fn cursor_to_end(&mut self)

Put the insertion point after the focused field’s last character.

Source

pub fn cursor_to_start(&mut self)

Put the insertion point before the focused field’s first character.

Source

pub fn move_cursor_left(&mut self)

Move the insertion point one character left (no-op at the start).

Source

pub fn move_cursor_right(&mut self)

Move the insertion point one character right (no-op at the end).

Source

pub fn move_cursor_word_left(&mut self)

Move the insertion point to the start of the previous word.

Skips the run of non-word characters before the caret first, then the word itself, which is the readline/Emacs rule Ctrl-Left follows.

Source

pub fn move_cursor_word_right(&mut self)

Move the insertion point to the end of the next word.

Source

pub fn delete_char(&mut self)

Delete the character before the insertion point (Backspace).

Source

pub fn delete_forward_char(&mut self)

Delete the character at the insertion point (Delete).

Source

pub fn delete_to_end(&mut self)

Delete from the insertion point to the end of the value (Ctrl-K).

Source

pub fn delete_to_start(&mut self)

Delete from the start of the value to the insertion point (Ctrl-U).

Source

pub fn delete_word_backward(&mut self)

Delete the word before the insertion point (Ctrl-W, Alt-Backspace).

Source

pub fn insert_char(&mut self, c: char)

Source

pub fn is_date_focus(&self) -> bool

Whether the focused field is a picker-only date field.

Source

pub fn focused_date_is_complete(&self) -> bool

Whether the focused date field already holds a complete, valid date.

Source

pub fn set_focused_date(&mut self, value: &str)

Overwrite the focused date field (no-op when it isn’t a date field).

Source

pub fn move_focus_next(&mut self)

Source

pub fn move_focus_prev(&mut self)

Trait Implementations§

Source§

impl Clone for FormState

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 FormState

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.