./textproc/treemd, TUI/CLI markdown navigator with tree-based structural navigation

[ CVSweb ] [ Homepage ] [ RSS ] [ Required by ]


Branch: CURRENT, Version: 0.5.12, Package name: treemd-0.5.12, Maintainer: pin

A markdown navigator with tree-based structural navigation.
Like tree, but interactive-navigate markdown documents using an
expandable/collapsible heading tree with a synchronized content view.

treemd is a modern markdown viewer that combines the structural clarity of the
tree command with powerful interactive navigation.
Whether you're exploring large documentation files, analyzing markdown
structure, or just reading comfortably in your terminal, treemd provides
both CLI tools for scripting and a beautiful TUI for interactive exploration.


Master sites:

Filesize: 4430.028 KB

Version history: (Expand)


CVS history: (Expand)


   2026-06-08 14:27:04 by pin | Files touched by this commit (3) | Package updated
Log message:
textproc/treemd: update to 0.5.12

[0.5.12] - 2026-06-06
Added

    Toggle mouse capture for text selection - New M shortcut and :toggle mouse \ 
capture palette command release the mouse so the terminal's native click-drag \ 
selection works for copying arbitrary text; toggle back to restore scroll-wheel \ 
navigation. The README also documents the Shift+drag bypass supported by most \ 
terminals
    Toggle heading markers in outline - New outline_heading_markers config \ 
option, # keyboard shortcut, and :toggle heading markers palette command to \ 
show/hide #/##/### level prefixes in the outline sidebar (default: true) (#57) \ 
— thanks to @alisaifee

Fixed

    Table copy keys did nothing useful - In interactive table mode y/Y/r had \ 
been silently rebound to generic copy/raw-source actions during the \ 
action-dispatch refactor, so cell, row, and copy-as-markdown copy were \ 
inoperative. Restored via dedicated CopyTableCell/CopyTableRow/CopyTableMarkdown \ 
actions wired to the existing handlers, with a regression test
    Inline backticks render as plain text - Inline code in table cells/headers, \ 
headings, and blockquotes now renders as styled inline code via \ 
format_inline_markdown() instead of literal backticks (#51, #53). Resolves the \ 
known issue carried in 0.5.11; requires turbovault-parser 1.5.0
    Navigation to duplicate headings - Selecting an outline entry whose text \ 
appears multiple times always jumped to the first occurrence. \ 
HeadingNode/OutlineItem now carry a position index, and all content-extraction, \ 
selection-restore, and rendering paths resolve by index. extract_section(text) \ 
is preserved for the CLI --section flag, delegating to a new \ 
extract_section_at_index() (#56) — thanks to @alisaifee
    snake_case corruption in subscript rendering - Terms like i_am_a_snake were \ 
mangled because _x was always treated as a LaTeX subscript. Subscript conversion \ 
now applies to _{x} unconditionally and to bare _x only when not mid-identifier \ 
(#58) — thanks to @alisaifee
    Mermaid image sizing and scrolling - Mermaid diagrams now expand to fit \ 
terminal width and scroll correctly (#53)

Changed

    Trimmed image format dependencies - ratatui-image 10 → 11 (dropped \ 
image-defaults) and image now opts into only the needed decoders (png, jpeg, \ 
gif, webp, bmp, ico, tiff), substantially shrinking the dependency tree
    Upgraded parser dependencies - turbovault-parser 1.4.1 → 1.5.0 and \ 
turbovault-core 1.4.1 → 1.5.0, plus transitive refreshes
    Removed outline auto-hide - Dropped the logic that auto-hid the outline when \ 
a directory contained few files; outline visibility is now driven solely by user \ 
toggle/config
    Hardened rendering and TTY handling - Tightened audit findings surfaced \ 
during PR #53 review across the CLI, table, and TUI rendering paths
   2026-04-28 19:46:03 by pin | Files touched by this commit (3) | Package updated
Log message:
textproc/treemd: update to 0.5.11

[0.5.11] - 2026-04-28
Fixed

    Toggle details no-op after section navigation - In interactive mode, \ 
pressing Enter on certain <details> blocks reported "✓ Toggled \ 
details" but produced no visible change. InteractiveState::element_states \ 
is keyed only by ElementId { block_idx, sub_idx }, so a previous section's Table \ 
state at a given block_idx silently blocked a fresh Details from initializing at \ 
the same key (the indexer used HashMap::entry().or_insert(), a no-op when \ 
present). toggle_details then matched no Details variant and silently failed. \ 
Indexer now overwrites stale wrong-variant entries while preserving same-section \ 
toggle state. Regression test added.
    --filter and --level ignored in --tree mode - CLI now honors both flags when \ 
rendering the tree output (c3c3fcd)
    --at-line not wired up; -s mismatched formatted headings - --at-line \ 
resolves to the enclosing heading; section selection (-s) now matches headings \ 
that contain inline formatting (36c4e60)

Changed

    Upgraded all dependencies to latest - Refreshed clap_complete 4.6.2 → \ 
4.6.3, mermaid-rs-renderer 0.2.1 → 0.2.2, turbovault-parser 1.4.0 → 1.4.1, \ 
turbovault-core 1.4.0 → 1.4.1, open 5.3.3 → 5.3.4, plus transitive refreshes \ 
(plist, wasm-bindgen, tokio, libc, js-sys, cc, etc.)

Tests

    Added end-to-end CLI integration suite covering --tree, --list, --filter, \ 
--level, --at-line, and -s (471d9d5)
    Added coverage for JSON output builder and config loading (ef250da)
    Added coverage for document tree/search and palette command matching (f185c4b)

Known Issues

    Inline backticks render as plain text instead of styled inline code in \ 
tables, headings, and blockquotes (#51). Fix in flight via #53, pending \ 
companion changes in turbovault-parser.
   2026-04-19 19:38:19 by pin | Files touched by this commit (3) | Package updated
Log message:
textproc/treemd: update to 0.5.10

[0.5.10] - 2026-04-16
Added

    Toggle hidden files and directories in file picker - Press h in the file \ 
picker to toggle visibility of dot-prefixed files and directories (e.g. \ 
.obsidian/, .notes.md); rebindable via the keybindings config (#52) — thanks \ 
to @ktaka-ccmp for the original directory-toggle implementation, extended in \ 
follow-up to cover hidden files as well

Fixed

    Content height u16 truncation - Changed content_height from u16 to usize to \ 
prevent silent overflow on documents with >65535 rendered lines; scroll \ 
clamped at ratatui's u16 boundary
    Terminal restoration when stdin is piped - disable_raw_mode now fully \ 
restores the original termios saved during enable_raw_mode, instead of only \ 
re-setting ICANON/ECHO/ISIG (which left IEXTEN, ICRNL, OPOST, etc. cleared by \ 
cfmakeraw)
    Table cell edit index using unreliable string search - \ 
calculate_current_table_index now uses the heading's byte offset from the \ 
document structure instead of content.find(), which could match the wrong \ 
occurrence in documents with repeated section text
    Panic on stdin read during terminal warning - Replaced \ 
stdin().read().unwrap() with non-panicking variant
    Silent config parse failure - Malformed config.toml now prints a warning \ 
instead of silently falling back to defaults

Changed

    Upgraded all dependencies to latest - Major: resvg 0.44 → 0.47. Minor: \ 
clap/clap_complete 4.5 → 4.6, indextree 4.7 → 4.8, indexmap 2.13 → 2.14, \ 
tempfile 3.26 → 3.27, toml 1.0 → 1.1, notify 8.0 → 8.2. Plus refreshed \ 
transitive deps (image, uuid, wayland-*, wasm-bindgen, zerocopy, etc.)
    Extracted current_section_content() helper - Deduplicated 9 instances of the \ 
section-content-extraction pattern across app.rs (-70 lines)
    Extracted resolve_relative_file_link() helper - Deduplicated identical \ 
relative-file-link resolution logic between follow_selected_link and \ 
follow_link_from_interactive (-50 lines)
    Extracted with_tty_stdin() helper in tty.rs - Deduplicated fd-swap logic \ 
shared by read_event and poll_event (-40 lines)
    Removed debug_output.txt from git tracking - Added to .gitignore
   2026-03-06 09:21:25 by pin | Files touched by this commit (3) | Package updated
Log message:
textproc/treemd: update to 0.5.9

[0.5.9] - 2026-03-04
Added

 - Dynamic help text - Help popup now displays actual configured keybindings \ 
instead of hardcoded key strings (#47)
     - User-customized keybindings are reflected in the help menu at render time
     - Structured HelpLine enum replaces raw string-based help entries

 - Noop action for keybinding customization - Users can unbind keys by mapping \ 
them to Noop in their config (#46)
     - Noop entries are automatically filtered from the help popup

 - Regression tests for keybinding system - Added tests for user config \ 
override, Noop unbinding, clone preservation, and help entry filtering

Fixed

 - Keybinding config merging - User-defined keybindings now correctly override \ 
defaults (#46)
     - Previously, defaults were inserted first in the dispatch Vec and matched \ 
before user overrides
     - New approach replaces matching default bindings in-place, preserving user \ 
precedence

 - Clone for Keybindings discarded user config - clone() always returned default \ 
keybindings; now properly clones binding state
 - Wrong action in help for "Exit interactive mode" - Help text used \ 
Quit (which exits the app) instead of ExitMode for table navigation exit
 - Duplicate t keybinding - Both ToggleTodoFilter and ToggleThemePicker were \ 
bound to t in Normal mode; ToggleTodoFilter moved to T (Shift+t)
 - Phantom S key in status bar - "S or :w to save" referenced an \ 
unbound key; updated to ":w to save"
 - Editor in interactive mode - OpenInEditor now jumps to the interactive \ 
element's source line instead of the selected heading (#45)
 - File picker missing from help menu - Added file picker entry to help text
 - Potential usize underflow in help text - Key column width calculation now \ 
uses saturating_sub

tl;dr:

 - Fix keybindings config merging by @enzalito in #46
 - Update help_text to display actual keybinds by @enzalito in #47
   2026-03-02 13:17:33 by pin | Files touched by this commit (1)
Log message:
textproc/treemd: reneble xdg-utils
   2026-03-02 13:11:14 by pin | Files touched by this commit (3) | Package updated
Log message:
textproc/treemd: update to 0.5.8

[0.5.8] - 2026-03-01
Added

    Folder navigation in file picker - Browse directories without leaving the \ 
TUI (#43)
        Subdirectories shown at bottom of file picker with [DIR] prefix and separator
        Press Enter on a directory to navigate into it
        Press Backspace to go to parent directory (works in both browse and \ 
search modes)
        Search filter applies to both files and directories

    Auto-hide outline for single files - Outline panel hides when directory \ 
contains 0-1 markdown files (#43)
        Automatically detected at startup and when navigating directories
        Can still be toggled manually with keybinding

Fixed

    Table crash at wide terminals - Fixed panic when rendering tables at \ 
terminal width >= 146 (#43)
        MIN_COL_WIDTH clamping could push total column width over budget after \ 
proportional shrink
        Added iterative trim loop to guarantee convergence
        Fixed infinite loop in padding reduction when needed_reduction < col_count

    EOF scroll accuracy - Scroll now stops precisely when last line reaches \ 
viewport bottom (#43)
        Uses ratatui's Paragraph::line_count() for accurate visual line count \ 
after word-wrapping
        Previously used raw line count, causing ~22% premature stop on wrapped \ 
content
        Consistent behavior across Down, Page Down, End, and all scroll methods

    Inline LaTeX command filtering - Commands now stripped when appearing \ 
inline, not just on their own line (#43)
        Handles: \begin{...}, \end{...}, \fontsize{...}{...}, \pagestyle{...}, \ 
\setlength{...}, \usepackage{...}, \renewcommand{...}, \newcommand{...}, \ 
\sethlcolor{...}, \titlespacing{...}, \pagenumbering{...}, \thispagestyle{...}, \ 
and more
        Strips bare commands like \Box$, \no, \yes that produce no visible content
        Inline font size commands (\small, \large, etc.) now removed when not on \ 
their own line

    Gapless cursor - Command palette cursor uses reverse-video space instead of \ 
█ for gap-free rendering (#43)

    Image position misalignment — Block images and paragraphs with inline \ 
images now reserve the correct number of placeholder lines in the interactive \ 
element indexer, matching the renderer (17 for block images, 14 for inline image \ 
paragraphs)

    Images not loading with non-standard extensions — Added \ 
with_guessed_format() to all image loading paths so content-type detection no \ 
longer relies solely on file extension

    LaTeX subscript mangling code spans - Inline code containing underscores \ 
(e.g., `post_tweet`) was corrupted by the LaTeX subscript converter, turning _t \ 
→ ₜ, _r → ᵣ, etc.
        Code spans (`), double-backtick spans, and fenced code blocks are now \ 
protected from all LaTeX transformations
        Fixes rendering of tables with code identifiers like post_tweet, \ 
my_variable, some_function

Changed

    Dependencies updated
        ratatui 0.30: added unstable-rendered-line-info feature for accurate \ 
line counting
        gif 0.13 → 0.14
        strum 0.27 → 0.28

Technical

    Performance: LaTeX regex caching - All ~80 regex patterns in strip_latex() \ 
now compiled once via OnceLock (previously compiled every render frame)
    Performance: Superscript/subscript lookup - Replaced O(N) linear array scans \ 
with match jump tables
    Performance: Directory scanning - Single-pass classification using \ 
entry.file_type() instead of separate is_file()/is_dir() stat syscalls
    Refactoring - Extracted max_content_scroll(), effective_picker_dir(), \ 
navigate_picker_to_dir(), is_markdown_extension(), and filter_by_name() helpers \ 
to eliminate code duplication
    Bug fix - scan_markdown_files() now recognizes .mdown extension (was missing \ 
from file picker scan)
    Performance: Image protocol caching — Images are now decoded from disk \ 
once when elements are indexed, then cached as StatefulProtocol objects. \ 
Previously, every ~16ms render frame re-decoded and re-created protocols from \ 
disk.
   2026-02-28 07:58:47 by pin | Files touched by this commit (3) | Package updated
Log message:
textproc/treemd: update to 0.5.7

[0.5.7] - 2026-02-26
Added

    Home/End key bindings - Navigate to first/last with Home/End keys (#43)
        Works in Normal, Interactive, Help, and FilePicker modes
        Also added PageUp/PageDown bindings in Normal mode for consistency

    Directory and multi-file support - Open file picker with directory argument (#43)
        treemd . opens file picker in current directory
        treemd docs/ opens file picker in specified directory
        Multiple file arguments supported (e.g., treemd *.md)

    Compact tree style - Gapless box-drawing characters for tree visualization (#43)
        Now uses ├── instead of ├─ (connected, no gaps)
        Config option tree_style: "compact" (default) or "spaced"
        Works in both --tree CLI output and query tree output

    Todo filter for outline - Filter heading tree to show only headings with \ 
open todos (#44)
        Press t to toggle filtering by open todos (- [ ] or * [ ])
        Shows only headings that contain open todos (directly or in descendants)
        Preserves hierarchy: parent headings shown if any child has todos
        Status message shows count of headings with open todos

    SOTA Content filtering - Robust YAML frontmatter and LaTeX handling (#43)
        Unicode Approximation: LaTeX math symbols like \alpha, \sum, \infty are \ 
now rendered as readable Unicode (α, ∑, ∞) instead of being stripped.
        Superscript/Subscript support: Common exponents and indices (like x^2, \ 
n_i) are converted to Unicode (x², nᵢ).
        Environment Preservation: Content inside LaTeX environments (like \ 
equation or align) is preserved while stripping the tags.
        hide_frontmatter option strips ---\n...\n--- blocks at document start.
        hide_latex option handles math and LaTeX commands robustly without \ 
"half measures".
        Aggressive filtering remains available but the standard mode is now \ 
preferred.

    Smart Responsive Tables - Tables now wrap and collapse intelligently (#43)
        Cell Wrapping: Long content now wraps into multiple lines within \ 
columns, ensuring data remains readable even on narrow terminals.
        Content-weighted widths: Uses 70% average + 30% max for fairer column \ 
distribution.
        Adaptive padding: Dynamically reduces cell padding (2 → 1 → 0) to \ 
save space.
        Unicode ellipsis: Optimized truncation using … for maximum information \ 
density.

    File picker quit - Press q to exit file picker dialog (#43)

Fixed

    EOF scroll behavior - Content no longer scrolls past the last line (#43)
        Now uses actual rendered line count (not raw markdown lines) for scroll \ 
limits
        Scroll stops when last line is visible at bottom of viewport
        Consistent behavior across all scroll methods (j/k, Page Up/Down, Home/End)

Technical

    Config additions (src/config.rs)
        Added ContentConfig struct with hide_frontmatter, hide_latex, \ 
latex_aggressive fields
        Added tree_style field to UiConfig (defaults to "compact")
        Added is_compact_tree() helper method to Config

    Content filtering utilities (src/tui/ui/util.rs)
        Added strip_frontmatter() for YAML frontmatter removal
        Added SOTA strip_latex() with Unicode symbol mapping and environment \ 
preservation
        Added wrap_text() utility for Unicode-aware word wrapping
        Added filter_content() combining all filters

    Tree rendering (src/parser/document.rs, src/query/output.rs)
        Added render_box_tree_styled() method with compact parameter
        Updated format_tree_value() to support compact mode

    App state (src/tui/app.rs)
        Added file_picker_dir field for custom directory support
        Added should_hide_frontmatter() and should_hide_latex() getters
        Updated scan_markdown_files() to use custom directory

    Table rendering (src/tui/ui/table.rs, src/tui/ui/mod.rs)
        Refactored render_table_row to return Vec<Line> for multi-line wrapping
        Implemented smart wrapping logic using util::wrap_text
        Propagated width adjustments through nested content structures
        Comprehensive test updates for new wrapping behavior
   2026-01-12 13:00:22 by pin | Files touched by this commit (3) | Package updated
Log message:
textproc/treemd: update to 0.5.6

[0.5.6] - 2026-01-09
Added

    Image configuration - Configure image rendering via [image] section in config
        Specify preferred renderer: renderer = "kitty" or renderer = \ 
"software"
        Add custom arguments: args = ["--no-animations"]
        Example config:

        [image]
        renderer = "kitty"
        args = ["--no-animations"]