Skip to main content

Picker

Struct Picker 

Source
pub struct Picker { /* private fields */ }
Expand description

Active completion dropdown state.

Implementations§

Source§

impl Picker

Source

pub fn visible_suggestions(&self) -> (usize, &[Suggestion])

Returns the centered five-row suggestion window and its first index.

Examples found in repository?
examples/chat/demo.rs (line 304)
300	fn paint_picker(pc: &mut PaintCtx<'_>, rect: Rect, y: u16, editor: &Editor) {
301		let Some(picker) = editor.picker() else {
302			return;
303		};
304		let (start, suggestions) = picker.visible_suggestions();
305		let overflow = picker.len() > suggestions.len();
306		let row_right = rect
307			.x
308			.saturating_add(rect.width.saturating_sub(u16::from(overflow)));
309		let primary_width = suggestions
310			.iter()
311			.filter_map(|suggestion| match suggestion.display() {
312				SuggestionDisplay::Text(name) => Some(visible_width(name).saturating_add(2)),
313				SuggestionDisplay::Emoji { .. } => None,
314			})
315			.max()
316			.unwrap_or(12)
317			.clamp(12, 32);
318
319		for (offset, suggestion) in suggestions.iter().enumerate() {
320			let Ok(offset) = u16::try_from(offset) else {
321				break;
322			};
323			let row = y.saturating_add(offset);
324			if row >= pc.clip {
325				break;
326			}
327			let selected = start + usize::from(offset) == picker.selected();
328			let label = if selected { ink(GREEN) } else { ink(TEXT) };
329			let description = if selected { ink(GREEN) } else { ink(MUTED) };
330			pc.frame.put(
331				rect.x,
332				row,
333				if selected {
334					pc.ctx.charset.cursor()
335				} else {
336					"  "
337				},
338				label,
339			);
340			match suggestion.display() {
341				SuggestionDisplay::Text(name) => {
342					draw_line(
343						pc.frame,
344						rect.x.saturating_add(2),
345						row,
346						row_right.saturating_sub(rect.x.saturating_add(2)),
347						&[Span::new(name, label)],
348					);
349					if let Some(text) = suggestion.description()
350						&& rect.width > 40
351					{
352						let description_x = rect
353							.x
354							.saturating_add(2)
355							.saturating_add(primary_width)
356							.min(row_right);
357						draw_line(
358							pc.frame,
359							description_x,
360							row,
361							row_right.saturating_sub(description_x),
362							&[Span::new(text, description)],
363						);
364					}
365				},
366				SuggestionDisplay::Emoji { emoji, shortcode } => {
367					let mut column = pc.frame.put(rect.x.saturating_add(2), row, emoji, label);
368					column = pc.frame.put(column, row, "  ", label);
369					if shortcode.starts_with(':') {
370						pc.frame.put(column, row, shortcode, label);
371					} else {
372						column = pc.frame.put(column, row, ":", label);
373						column = pc.frame.put(column, row, shortcode, label);
374						pc.frame.put(column, row, ":", label);
375					}
376				},
377			}
378		}
379
380		if overflow && !suggestions.is_empty() {
381			let (track, thumb_glyph) = pc.ctx.charset.scrollbar();
382			let track_x = rect.x.saturating_add(rect.width.saturating_sub(1));
383			for offset in 0..suggestions.len() {
384				let Ok(offset) = u16::try_from(offset) else {
385					break;
386				};
387				pc.frame
388					.put(track_x, y.saturating_add(offset), track, ink(FAINT));
389			}
390			let thumb = picker
391				.selected()
392				.saturating_mul(suggestions.len().saturating_sub(1))
393				/ picker.len().saturating_sub(1);
394			pc.frame.put(
395				track_x,
396				y.saturating_add(u16::try_from(thumb).unwrap_or(u16::MAX)),
397				thumb_glyph,
398				ink(GREEN),
399			);
400		}
401	}
Source

pub const fn selected(&self) -> usize

Returns the selected suggestion’s absolute index.

Examples found in repository?
examples/chat/demo.rs (line 327)
300	fn paint_picker(pc: &mut PaintCtx<'_>, rect: Rect, y: u16, editor: &Editor) {
301		let Some(picker) = editor.picker() else {
302			return;
303		};
304		let (start, suggestions) = picker.visible_suggestions();
305		let overflow = picker.len() > suggestions.len();
306		let row_right = rect
307			.x
308			.saturating_add(rect.width.saturating_sub(u16::from(overflow)));
309		let primary_width = suggestions
310			.iter()
311			.filter_map(|suggestion| match suggestion.display() {
312				SuggestionDisplay::Text(name) => Some(visible_width(name).saturating_add(2)),
313				SuggestionDisplay::Emoji { .. } => None,
314			})
315			.max()
316			.unwrap_or(12)
317			.clamp(12, 32);
318
319		for (offset, suggestion) in suggestions.iter().enumerate() {
320			let Ok(offset) = u16::try_from(offset) else {
321				break;
322			};
323			let row = y.saturating_add(offset);
324			if row >= pc.clip {
325				break;
326			}
327			let selected = start + usize::from(offset) == picker.selected();
328			let label = if selected { ink(GREEN) } else { ink(TEXT) };
329			let description = if selected { ink(GREEN) } else { ink(MUTED) };
330			pc.frame.put(
331				rect.x,
332				row,
333				if selected {
334					pc.ctx.charset.cursor()
335				} else {
336					"  "
337				},
338				label,
339			);
340			match suggestion.display() {
341				SuggestionDisplay::Text(name) => {
342					draw_line(
343						pc.frame,
344						rect.x.saturating_add(2),
345						row,
346						row_right.saturating_sub(rect.x.saturating_add(2)),
347						&[Span::new(name, label)],
348					);
349					if let Some(text) = suggestion.description()
350						&& rect.width > 40
351					{
352						let description_x = rect
353							.x
354							.saturating_add(2)
355							.saturating_add(primary_width)
356							.min(row_right);
357						draw_line(
358							pc.frame,
359							description_x,
360							row,
361							row_right.saturating_sub(description_x),
362							&[Span::new(text, description)],
363						);
364					}
365				},
366				SuggestionDisplay::Emoji { emoji, shortcode } => {
367					let mut column = pc.frame.put(rect.x.saturating_add(2), row, emoji, label);
368					column = pc.frame.put(column, row, "  ", label);
369					if shortcode.starts_with(':') {
370						pc.frame.put(column, row, shortcode, label);
371					} else {
372						column = pc.frame.put(column, row, ":", label);
373						column = pc.frame.put(column, row, shortcode, label);
374						pc.frame.put(column, row, ":", label);
375					}
376				},
377			}
378		}
379
380		if overflow && !suggestions.is_empty() {
381			let (track, thumb_glyph) = pc.ctx.charset.scrollbar();
382			let track_x = rect.x.saturating_add(rect.width.saturating_sub(1));
383			for offset in 0..suggestions.len() {
384				let Ok(offset) = u16::try_from(offset) else {
385					break;
386				};
387				pc.frame
388					.put(track_x, y.saturating_add(offset), track, ink(FAINT));
389			}
390			let thumb = picker
391				.selected()
392				.saturating_mul(suggestions.len().saturating_sub(1))
393				/ picker.len().saturating_sub(1);
394			pc.frame.put(
395				track_x,
396				y.saturating_add(u16::try_from(thumb).unwrap_or(u16::MAX)),
397				thumb_glyph,
398				ink(GREEN),
399			);
400		}
401	}
Source

pub const fn len(&self) -> usize

Returns the total number of matching suggestions.

Examples found in repository?
examples/chat/demo.rs (line 305)
300	fn paint_picker(pc: &mut PaintCtx<'_>, rect: Rect, y: u16, editor: &Editor) {
301		let Some(picker) = editor.picker() else {
302			return;
303		};
304		let (start, suggestions) = picker.visible_suggestions();
305		let overflow = picker.len() > suggestions.len();
306		let row_right = rect
307			.x
308			.saturating_add(rect.width.saturating_sub(u16::from(overflow)));
309		let primary_width = suggestions
310			.iter()
311			.filter_map(|suggestion| match suggestion.display() {
312				SuggestionDisplay::Text(name) => Some(visible_width(name).saturating_add(2)),
313				SuggestionDisplay::Emoji { .. } => None,
314			})
315			.max()
316			.unwrap_or(12)
317			.clamp(12, 32);
318
319		for (offset, suggestion) in suggestions.iter().enumerate() {
320			let Ok(offset) = u16::try_from(offset) else {
321				break;
322			};
323			let row = y.saturating_add(offset);
324			if row >= pc.clip {
325				break;
326			}
327			let selected = start + usize::from(offset) == picker.selected();
328			let label = if selected { ink(GREEN) } else { ink(TEXT) };
329			let description = if selected { ink(GREEN) } else { ink(MUTED) };
330			pc.frame.put(
331				rect.x,
332				row,
333				if selected {
334					pc.ctx.charset.cursor()
335				} else {
336					"  "
337				},
338				label,
339			);
340			match suggestion.display() {
341				SuggestionDisplay::Text(name) => {
342					draw_line(
343						pc.frame,
344						rect.x.saturating_add(2),
345						row,
346						row_right.saturating_sub(rect.x.saturating_add(2)),
347						&[Span::new(name, label)],
348					);
349					if let Some(text) = suggestion.description()
350						&& rect.width > 40
351					{
352						let description_x = rect
353							.x
354							.saturating_add(2)
355							.saturating_add(primary_width)
356							.min(row_right);
357						draw_line(
358							pc.frame,
359							description_x,
360							row,
361							row_right.saturating_sub(description_x),
362							&[Span::new(text, description)],
363						);
364					}
365				},
366				SuggestionDisplay::Emoji { emoji, shortcode } => {
367					let mut column = pc.frame.put(rect.x.saturating_add(2), row, emoji, label);
368					column = pc.frame.put(column, row, "  ", label);
369					if shortcode.starts_with(':') {
370						pc.frame.put(column, row, shortcode, label);
371					} else {
372						column = pc.frame.put(column, row, ":", label);
373						column = pc.frame.put(column, row, shortcode, label);
374						pc.frame.put(column, row, ":", label);
375					}
376				},
377			}
378		}
379
380		if overflow && !suggestions.is_empty() {
381			let (track, thumb_glyph) = pc.ctx.charset.scrollbar();
382			let track_x = rect.x.saturating_add(rect.width.saturating_sub(1));
383			for offset in 0..suggestions.len() {
384				let Ok(offset) = u16::try_from(offset) else {
385					break;
386				};
387				pc.frame
388					.put(track_x, y.saturating_add(offset), track, ink(FAINT));
389			}
390			let thumb = picker
391				.selected()
392				.saturating_mul(suggestions.len().saturating_sub(1))
393				/ picker.len().saturating_sub(1);
394			pc.frame.put(
395				track_x,
396				y.saturating_add(u16::try_from(thumb).unwrap_or(u16::MAX)),
397				thumb_glyph,
398				ink(GREEN),
399			);
400		}
401	}
Source

pub const fn is_empty(&self) -> bool

Reports whether no suggestions matched (never true for a live picker).

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> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
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, U> TryFrom<U> for T
where U: Into<T>,

Source§

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>,

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.