Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more documentation #166

Merged
merged 1 commit into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 185 additions & 1 deletion src/base.rs

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! # Default Commands
//!
//! The command-bar commands are set up here, and iamb-specific commands are defined here. See
//! [modalkit::env::vim::command] for additional Vim commands we pull in.
use std::convert::TryFrom;

use matrix_sdk::ruma::{events::tag::TagName, OwnedUserId};
Expand Down Expand Up @@ -555,6 +559,7 @@ fn add_iamb_commands(cmds: &mut ProgramCommands) {
});
}

/// Initialize the default command state.
pub fn setup_commands() -> ProgramCommands {
let mut cmds = ProgramCommands::default();

Expand Down
1 change: 1 addition & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! # Logic for loading and validating application configuration
use std::borrow::Cow;
use std::collections::hash_map::DefaultHasher;
use std::collections::HashMap;
Expand Down
5 changes: 5 additions & 0 deletions src/keybindings.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! # Default Keybindings
//!
//! The keybindings are set up here. We define some iamb-specific keybindings, but the default Vim
//! keys come from [modalkit::env::vim::keybindings].
use modalkit::{
editing::action::WindowAction,
env::vim::keybindings::{InputStep, VimBindings},
Expand All @@ -10,6 +14,7 @@ use crate::base::{IambAction, IambInfo, Keybindings, MATRIX_ID_WORD};

type IambStep = InputStep<IambInfo>;

/// Initialize the default keybinding state.
pub fn setup_keybindings() -> Keybindings {
let mut ism = Keybindings::empty();

Expand Down
14 changes: 14 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
//! # iamb
//!
//! The iamb client loops over user input and commands, and turns them into actions, [some of
//! which][IambAction] are specific to iamb, and [some of which][Action] come from [modalkit]. When
//! adding new functionality, you will usually want to extend [IambAction] or one of its variants
//! (like [RoomAction][base::RoomAction]), and then add an appropriate [command][commands] or
//! [keybinding][keybindings].
//!
//! For more complicated changes, you may need to update [the async worker thread][worker], which
//! handles background Matrix tasks with [matrix-rust-sdk][matrix_sdk].
//!
//! Most rendering logic lives under the [windows] module, but [Matrix messages][message] have
//! their own module.
#![allow(clippy::manual_range_contains)]
#![allow(clippy::needless_return)]
#![allow(clippy::result_large_err)]
Expand Down Expand Up @@ -200,6 +213,7 @@ fn setup_screen(
return Ok(ScreenState::new(win, cmd));
}

/// The main application state and event loop.
struct Application {
/// Terminal backend.
terminal: Terminal<CrosstermBackend<Stdout>>,
Expand Down
11 changes: 10 additions & 1 deletion src/message/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ use crate::{
util::{join_cell_text, space_text},
};

struct BulletIterator {
/// Generate bullet points from a [ListStyle].
pub struct BulletIterator {
style: ListStyle,
pos: usize,
len: usize,
Expand Down Expand Up @@ -74,6 +75,7 @@ impl Iterator for BulletIterator {
}
}

/// Whether this list is ordered or unordered.
#[derive(Clone, Copy, Debug)]
pub enum ListStyle {
Ordered,
Expand All @@ -88,11 +90,13 @@ impl ListStyle {

pub type StyleTreeChildren = Vec<StyleTreeNode>;

/// Type of contents in a table cell.
pub enum CellType {
Data,
Header,
}

/// A collection of cells for a single row in a table.
pub struct TableRow {
cells: Vec<(CellType, StyleTreeNode)>,
}
Expand All @@ -103,6 +107,7 @@ impl TableRow {
}
}

/// A collection of rows in a table.
pub struct TableSection {
rows: Vec<TableRow>,
}
Expand All @@ -113,6 +118,7 @@ impl TableSection {
}
}

/// A table.
pub struct Table {
caption: Option<Box<StyleTreeNode>>,
sections: Vec<TableSection>,
Expand Down Expand Up @@ -229,6 +235,7 @@ impl Table {
}
}

/// A processed HTML element that we can render to the terminal.
pub enum StyleTreeNode {
Blockquote(Box<StyleTreeNode>),
Break,
Expand Down Expand Up @@ -380,6 +387,7 @@ impl StyleTreeNode {
}
}

/// A processed HTML document.
pub struct StyleTree {
children: StyleTreeChildren,
}
Expand Down Expand Up @@ -649,6 +657,7 @@ fn dom_to_style_tree(dom: RcDom) -> StyleTree {
StyleTree { children: h2t(&dom.document) }
}

/// Parse an HTML document from a string.
pub fn parse_matrix_html(s: &str) -> StyleTree {
let dom = parse_fragment(
RcDom::default(),
Expand Down
1 change: 1 addition & 0 deletions src/message/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! # Room Messages
use std::borrow::Cow;
use std::cmp::{Ord, Ordering, PartialOrd};
use std::collections::hash_map::DefaultHasher;
Expand Down
19 changes: 19 additions & 0 deletions src/message/printer.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//! # Line Wrapping Logic
//!
//! The [TextPrinter] handles wrapping stylized text and inserting spaces for padding at the end of
//! lines to make concatenation work right (e.g., combining table cells after wrapping their
//! contents).
use std::borrow::Cow;

use modalkit::tui::layout::Alignment;
Expand All @@ -8,6 +13,7 @@ use unicode_width::UnicodeWidthStr;

use crate::util::{space_span, take_width};

/// Wrap styled text for the current terminal width.
pub struct TextPrinter<'a> {
text: Text<'a>,
width: usize,
Expand All @@ -21,6 +27,7 @@ pub struct TextPrinter<'a> {
}

impl<'a> TextPrinter<'a> {
/// Create a new printer.
pub fn new(width: usize, base_style: Style, hide_reply: bool) -> Self {
TextPrinter {
text: Text::default(),
Expand All @@ -35,24 +42,29 @@ impl<'a> TextPrinter<'a> {
}
}

/// Configure the alignment for each line.
pub fn align(mut self, alignment: Alignment) -> Self {
self.alignment = alignment;
self
}

/// Set whether newlines should be treated literally, or turned into spaces.
pub fn literal(mut self, literal: bool) -> Self {
self.literal = literal;
self
}

/// Indicates whether replies should be pushed to the printer.
pub fn hide_reply(&self) -> bool {
self.hide_reply
}

/// Indicates the current printer's width.
pub fn width(&self) -> usize {
self.width
}

/// Create a new printer with a smaller width.
pub fn sub(&self, indent: usize) -> Self {
TextPrinter {
text: Text::default(),
Expand All @@ -71,6 +83,7 @@ impl<'a> TextPrinter<'a> {
self.width - self.curr_width
}

/// If there is any text on the current line, start a new one.
pub fn commit(&mut self) {
if self.curr_width > 0 {
self.push_break();
Expand All @@ -82,6 +95,7 @@ impl<'a> TextPrinter<'a> {
self.text.lines.push(Spans(std::mem::take(&mut self.curr_spans)));
}

/// Start a new line.
pub fn push_break(&mut self) {
if self.curr_width == 0 && self.text.lines.is_empty() {
// Disallow leading breaks.
Expand Down Expand Up @@ -149,6 +163,7 @@ impl<'a> TextPrinter<'a> {
}
}

/// Push a [Span] that isn't allowed to break across lines.
pub fn push_span_nobreak(&mut self, span: Span<'a>) {
let sw = UnicodeWidthStr::width(span.content.as_ref());

Expand All @@ -161,6 +176,7 @@ impl<'a> TextPrinter<'a> {
self.curr_width += sw;
}

/// Push text with a [Style].
pub fn push_str(&mut self, s: &'a str, style: Style) {
let style = self.base_style.patch(style);

Expand Down Expand Up @@ -212,16 +228,19 @@ impl<'a> TextPrinter<'a> {
}
}

/// Push [Spans] into the printer.
pub fn push_line(&mut self, spans: Spans<'a>) {
self.commit();
self.text.lines.push(spans);
}

/// Push multiline [Text] into the printer.
pub fn push_text(&mut self, text: Text<'a>) {
self.commit();
self.text.lines.extend(text.lines);
}

/// Render the contents of this printer as [Text].
pub fn finish(mut self) -> Text<'a> {
self.commit();
self.text
Expand Down
1 change: 1 addition & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! # Utility functions
use std::borrow::Cow;

use unicode_segmentation::UnicodeSegmentation;
Expand Down
8 changes: 8 additions & 0 deletions src/windows/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
//! # Windows for the User Interface
//!
//! This module contains the logic for rendering windows, and handling UI actions that get
//! delegated to individual windows/UI elements (e.g., typing text or selecting a list item).
//!
//! Additionally, some of the iamb commands delegate behaviour to the current UI element. For
//! example, [sending messages][crate::base::SendAction] delegate to the [room window][RoomState],
//! where we have the message bar and room ID easily accesible and resetable.
use std::cmp::{Ord, Ordering, PartialOrd};
use std::ops::Deref;
use std::sync::Arc;
Expand Down
3 changes: 3 additions & 0 deletions src/windows/room/chat.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! Window for Matrix rooms
use std::borrow::Cow;
use std::ffi::{OsStr, OsString};
use std::fs;
Expand Down Expand Up @@ -85,6 +86,7 @@ use crate::worker::Requester;

use super::scrollback::{Scrollback, ScrollbackState};

/// State needed for rendering [Chat].
pub struct ChatState {
room_id: OwnedRoomId,
room: MatrixRoom,
Expand Down Expand Up @@ -786,6 +788,7 @@ impl Promptable<ProgramContext, ProgramStore, IambInfo> for ChatState {
}
}

/// [StatefulWidget] for Matrix rooms.
pub struct Chat<'a> {
store: &'a mut ProgramStore,
focused: bool,
Expand Down
6 changes: 6 additions & 0 deletions src/windows/room/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! # Windows for Matrix rooms and spaces
use matrix_sdk::{
room::{Invited, Room as MatrixRoom},
ruma::{
Expand Down Expand Up @@ -79,6 +80,11 @@ macro_rules! delegate {
};
}

/// State for a Matrix room or space.
///
/// Since spaces function as special rooms within Matrix, we wrap their window state together, so
/// that operations like sending and accepting invites, opening the members window, etc., all work
/// similarly.
pub enum RoomState {
Chat(ChatState),
Space(SpaceState),
Expand Down
1 change: 1 addition & 0 deletions src/windows/room/scrollback.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! Message scrollback
use std::collections::HashSet;

use regex::Regex;
Expand Down
3 changes: 3 additions & 0 deletions src/windows/room/space.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! Window for Matrix spaces
use std::ops::{Deref, DerefMut};
use std::time::{Duration, Instant};

Expand Down Expand Up @@ -25,6 +26,7 @@ use crate::windows::RoomItem;

const SPACE_HIERARCHY_DEBOUNCE: Duration = Duration::from_secs(5);

/// State needed for rendering [Space].
pub struct SpaceState {
room_id: OwnedRoomId,
room: MatrixRoom,
Expand Down Expand Up @@ -86,6 +88,7 @@ impl DerefMut for SpaceState {
}
}

/// [StatefulWidget] for Matrix spaces.
pub struct Space<'a> {
focused: bool,
store: &'a mut ProgramStore,
Expand Down
1 change: 1 addition & 0 deletions src/windows/welcome.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//! Welcome Window
use std::ops::{Deref, DerefMut};

use modalkit::tui::{buffer::Buffer, layout::Rect};
Expand Down
4 changes: 4 additions & 0 deletions src/worker.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! # Async Matrix Client Worker
//!
//! The worker thread handles asynchronous work, and can receive messages from the main thread that
//! block on a reply from the async worker.
use std::collections::HashMap;
use std::convert::TryFrom;
use std::fmt::{Debug, Formatter};
Expand Down