mdless
More Markdown, Less less
- Features
- Installation
- Usage
- Configuration
- Customization
- Integrations
- Similar Projects
- Roadmap
- Changelog
mdless
is a utility that provides a formatted and highlighted view of Markdown files in Terminal.
I often use iTerm2 in visor mode, so qlmanage -p
is annoying. I still wanted a way to view Markdown files quickly and without cruft.
Features
- Built in pager functionality with pipe capability,
less
replacement for Markdown files - Format tables
- Colorize Markdown syntax for most elements
- Normalize spacing and link formatting
- Display footnotes after each paragraph
- Inline image display (local, optionally remote) (with compatible tools like imgcat or chafa)
- Syntax highlighting of code blocks when Pygments is installed
- List headlines in document
- Display single section of the document based on headlines
- Configurable Markdown options
- Customizable colors
- Add iTerm marks for h1-3 navigation when pager is disabled
- TaskPaper syntax detection and highlighting
Installation
Gem install
gem install mdless
If you run into errors, try gem install --user-install mdless
, or sudo gem install mdless
(in that order).
Homebrew
mdless is also available via Homebrew (directly).
brew install mdless
Dependencies
To render images, you need imgcat
or chafa
installed (brew install chafa
).
For syntax highlighting, the pygmentize
command must be available, part of the Pygments package (brew install pygments
).
Usage
mdless [options] path
or cat [path] | mdless
The pager used is determined by system configuration in this order of preference:
$PAGER
less
more
cat
pager
Options
-c, --[no-]color Colorize output (default on)
-d, --debug LEVEL Level of debug messages to output (1-4, 4 to see all messages)
-h, --help Display this screen
-i, --images=TYPE Include [local|remote (both)|none] images in output (requires chafa or imgcat, default none).
-I, --all-images Include local and remote images in output (requires imgcat or chafa)
-l, --list List headers in document and exit
-p, --[no-]pager Formatted output to pager (default on)
-P Disable pager (same as --no-pager)
-s, --section=NUMBER[,NUMBER] Output only a headline-based section of the input (numeric from --list)
-t, --theme=THEME_NAME Specify an alternate color theme to load
-@, --at_tags Highlight @tags and values in the document
-v, --version Display version number
-w, --width=COLUMNS Column width to format for (default: terminal width)
--[no-]autolink Convert bare URLs and emails to <links>
--[no-]inline_footnotes Display footnotes immediately after the paragraph that references them
--[no-]intra-emphasis Parse emphasis inside of words (e.g. Mark_down_)
--[no-]lax-spacing Allow lax spacing
--links=FORMAT Link style ([inline, reference, paragraph], default inline,
"paragraph" will position reference links after each paragraph)
--[no-]linebreaks Preserve line breaks
--[no-]syntax Syntax highlight code blocks
--taskpaper=OPTION Highlight TaskPaper format (true|false|auto)
--update_config Update the configuration file with new keys and current command line options
--[no-]wiki-links Highlight [[wiki links]]
Configuration
The first time mdless is run, a config file will be written to ~/.config/mdless/config.yml
, based on the command line options used on the first run. Update that file to make any options permanent (config options will always be overridden by command line flags).
---
:at_tags: true
:autolink: true
:color: true
:inline_footnotes: true
:intra_emphasis: false
:lax_spacing: true
:links: :paragraph
:local_images: true
:pager: true
:preserve_linebreaks: false
:remote_images: false
:syntax_higlight: true
:taskpaper: :auto
:theme: default
:width: 120
:wiki_links: true
- The
:at_tags
setting determines whether @tags will be highlighted. If this is enabled, colors will be pulled from theat_tags
settings in the theme. :autolink
will determine whether bare urls are turned into<self-linking>
urls.:color
will enable or disable all coloring.:inline_footnotes
will determine the placement of footnotes. If true, footnotes will be added directly after the element that refers to them.:intra_emphasis
will determine whether words containing underscores are rendered as italics or not.:lax_spacing
determines whether a blank line is required around HTML elements.:links
can beinline
,reference
, orparagraph
. Paragraph puts reference links directly after the graf that refers to them.:local_images
determines whether local images are processed usingchafa
orimgcat
(whichever is available).:remote_images
does the same for images referenced with web urls. If:remote_images
is true, then:local_images
is automatically enabled.:pager
turns on or off pagination usingless
or closest available substitute.:preserve_linebreaks
determines whether hard breaks within paragraphs are preserved. When converting to HTML, most Markdown processors will cause consecutive lines to be merged together, which is the default behavior formdless
. Turning this option on will cause lines to remain hard wrapped.:syntax_highlight
will turn on/off syntax highlighting of code blocks (requires Pygments):taskpaper
determines whether a file is rendered as a TaskPaper document. This can be set to:auto
to have TaskPaper detected from extension or content.:theme
allows you to specify an alternate theme. See Customization below.:width
allows you to permanantly set a width for wrapping of lines. If the width specified is greater than the available columns of the display, the display columns will be used instead.:wiki_links
determines whether[[wiki links]]
will be highlighted. If highlighted, colors are pulled from thelink
section of the theme.
Customization
On first run a default theme file will be placed in ~/.config/mdless/mdless.theme
. You can edit this file to modify the colors mdless uses when highlighting your files. You can copy this file and create multiple theme options which can be specified with the -t NAME
option. For example, create ~/.config/mdless/brett.theme
and then call mdless -t brett filename.md
.
Colors are limited to basic ANSI codes, with support for bold, underline, italics (if available for the terminal/font), dark and bright, and foreground and background colors.
Customizeable settings are stored in YAML format. A chunk of the settings file looks like this:
h1:
color: b intense_black on_white
pad: d black on_white
pad_char: "="
Font and color settings are set using a string of color names and modifiers. A typical string looks like b red on_white
, which would give you a bold red font on a white background. In the YAML settings file there’s no need for quotes, just put the string following the colon for the setting.
You can also use 3 or 6-digit hex codes in place of color names. These can be prefixed with bg
or on_
to affect background colors, e.g. bgFF0ACC
. The codes are case-insensitive and can be combined with emphasis modifiers like b
or u
.
Some extra (non-color) settings are available for certain keys, e.g. pad_char
to define the right padding character used on level 1 and 2 headlines. Note that you can change the Pygments theme used for syntax highlighting with the code_block.pygments_theme setting. For a list of available styles (assuming you have Pygments installed), use pygmentize -L styles
.
The display of characters around emphasis and code spans can be configured. By default, the surrounding character for bold is **
, italic is _
, and code span is a backtick. You can leave these keys empty to not display characters at all. For triple-emphasized text, the text will be surrounded by italic and bold characters, in that order.
emphasis:
bold: b
bold_character: "**"
italic: u i
italic_character: ""
bold-italic: b u i
code_span:
marker: b white
color: b white on_intense_black
character: ""
Note: the ANSI escape codes are reset every time the color changes, so, for example, if you have a key that defines underlines for the url in a link, the underline will automatically be removed when it gets to a bracket. This also means that if you define a background color, you’ll need to define it again on all the keys that it should affect.
Base colors:
- black
- red
- green
- yellow
- blue
- magenta
- cyan
- white
Emphasis:
- b (bold)
- d (dark)
- i (italic)
- u (underline)
- r (reverse, negative)
To modify the emphasis, use ‘b’ (bold), ‘i’ (italic), ‘u’ (underline), e.g. u yellow
for underlined yellow. These can be combined, e.g. b u red
.
Use ‘r’ to reverse foreground and background colors. r white on_black
would display as black on_white
. ‘r’ alone will reverse the current color set for a line.
To set a background color, use on_[color]
with one of the 8 colors. This can be used with foreground colors in the same setting, e.g. white on_black
.
Use ‘d’ (dark) to indicate the darker version of a foreground color. On macOS (and possibly other systems) you can use the brighter version of a color by prefixing with “intense”, e.g. intense_red
or on_intense_black
.
Integrations
Ranger
Ranger is a file manager that allows for quick navigation in the file hierarchy. A preview can be displayed for various file types. See docs at https://github.com/ranger/ranger/wiki.
mdless can be used in Ranger to preview Markdown and Taskpaper.
Ranger is installed with brew install ranger
.
With ranger --copy-config=scope
the configuration file for previews scope.sh
is created in the directory ~/.config/ranger
.
The configuration file is already preconfigured. The following can be inserted above html to use mdless.
## Markdown
md|taskpaper)
mdless --taskpaper=auto -@ "${FILE_PATH}" && exit 5
;;
Thanks to Ralf Hülsmann for contributing!
Gather
Gather is a tool for converting web pages to Markdown. You can use it with mdless to create a Lynx-style web browser:
$ gather https://brettterpstra.com/projects/gather-cli/ | mdless
fzf
fzf is a tool for selecting files and other menu options with typeahead fuzzy matching. You can set up mdless
as a previewer when selecting Markdown or TaskPaper files.
$ ls *.md | fzf --preview 'mdless {}'
Fish
You can replace the cat command in Fish by creating the following functions in ~/.config/fish/functions
get_ext.fish
function get_ext -d 'Get the file extension from the argument'
set -l splits (string split "." $argv)
echo $splits[-1]
end
cat.fish
function cat -d "Use bat instead of cat unless it's a Markdown file, then use mdless"
set -l exts md markdown txt taskpaper
if not test -f $argv[-1]
echo "File not found: $argv[-1]"
return 0
end
if contains (get_ext $argv[-1]) $exts
mdless $argv
else
command bat --style plain --theme OneHalfDark $argv
end
end
Note that if you do this, and you need uncolored output to pipe somewhere, you’ll need to use command cat FILE
to revert to the built-in cat
. Otherwise your text will be full of the escape codes that mdless
uses to colorize the output.
Similar Projects
There are a few great options for Markdown viewing in the Terminal. If mdless
doesn’t do it for you, check out:
Roadmap
Things I might get around to adding:
- Re-implement option to convert all links to reference links for display
- allow multiple theme files with command line option to specify
Changelog
Click to expand
- 2.1.35
- Ruby 2.7 error (again)
- 2.1.30
- Error when $EDITOR is not defined
- 2.1.29
- More code cleanup, help output improvements
- Line breaks in help output
- This release should fix an error on Ruby 2.7 in string.rb
- 2.1.28
- Default to 0 width, which makes the width the column width of the terminal
- Don’t save a –width setting to config, require that to be manually updated if desired
- 2.1.27
- Error handling when YAML can’t be processed
- 2.1.25
- YAML loading issues caused by safe_load
- 2.1.24
- Save MultiMarkdown metadata into a hash
- Allow [%metakey] replacements
- Allow {{filename}} transcusions (MultiMarkdown), respects “transclude base:” metadata
- Transclude documents with
{{filename}}
, nesting allowed, “transclude base:” metadata respected (even in YAML) - Metadata can be used in
[%key]
format to have it replaced in the output based on metadata values - 2.1.23
- Fix release pipeline to get version number correct in git release
- Changelog mismatch
- 2.1.22
- TaskPaper file with metadata causing negative argument error
- Remove
<br>
from metadata - YAML metadata and negative line lengths »»»> release/2.1.30
- 2.1.14
- Spaces on a line separating metadata won’t break display
- Preserve line breaks in metadata
- Failure to display metadata fixed
- 2.1.13
- Remove debugging statement
- 2.1.12
- Fix list indentation when nesting
- 2.1.11
- Better regex for highlighting raw HTML
- Indentation in highlighted code blocks
- HTML Tag highlighting breaking pre/post color conversion
- 2.1.10
- Spinner while processing to indicate working
- Image links can now be converted to reference format, with correct coloring
- Render image links before reference link conversion
- 2.1.9
- Code block prefix configurable, can be left empty to make more copyable code blocks
- Remove empty lines from block quotes
- Infinite loop when calculating ANSI emphasis
- Don’t accept colors or semicolons inside of @tag names
- 2.1.8
- –update-theme option to add any missing keys to your theme file
- Strip ul_char of any spaces before inserting
- 2.1.7
- Dedup and remove empty escape codes before output
- Tables losing column alignment
- Unneccessarily long table cells
- 2.1.6
- In addition to color names, you can now use 3 or 6-digit hex codes, prefix with “bg” or “on_” to affect background color
- Better highlighting of h1/h2 when header contains a link
- List items with multiple paragraphs incorrectly highlighted
- 2.1.3
- Respect :width setting in config
- 2.0.24
- Update readme with config descriptions
- Code blocks containing YAML with
---
as the first line were being interpreted as Setext headers - Line breaks being consumed when matching tags for highlighting
- 2.0.21
- When converting to reference links, catch links that have been wrapped
- 2.0.20
- Subsequent tables inheriting first table’s column count
- 2.0.19
--section
can take string arguments to be fuzzy matched against headlines- Code refactoring
- TaskPaper formatting now responds to –section with string matches
- TaskPaper formatting now responds to –list to list projects
- TaskPaper auto detection double checks content by removing all projects and tasks and seeing if there’s anything left before deciding it’s not TaskPaper content
- Extra line break before headers
- Wrap block quotes to max width
- Missing first headline in output
- Long links that were wrapped were not being replaced when converting to reference links
- 2.0.18
- Better handling of default options set in config
- More expansive detection of screen width, no longer just dependent on
tput
being available - Only extend borders and backgrounds on code blocks to the length of the longest line
- Include the language in the top border of code blocks, if available
- Validate themes and lexers using
pygmentize
output, with fallbacks - If width specified in config is greater than display columns, fall back to display columns as max width
- Metadata (MMD/YAML) handling on TaskPaper files
- 2.0.17
- Re-order command line options for more readable help output (
mdless -h
) - 2.0.15
- Highlight [[wiki links]]
- TaskPaper rendering refinements
- Handle TaskPaper tasks without project if –taskpaper is enabled
- Wiki link highlighting is optional with
--[no-]wiki-links
and can be set in config - Nil error on short files
- Project regex matching
- PROJECT NAME:
- If taskpaper is true, avoid all parsing other than tasks, projects, notes, and tags
- 2.0.8
- Image rendering with chafa improved, still have to figure out a way to make sure content breaks around the embedded image
- Only detect mmd headers on first line
- 2.0.7
- Render links as reference links at the end of the file (
--links ref
) or per-paragraph (--links para
). Defaults to inline (--links inline
) - Pad numbers on headline listing to preserve indentation
- 2.0.6
- Render links as reference links at the end of the file (
--links ref
) or per-paragraph (--links para
). Defaults to inline (--links inline
) - Pad numbers on headline listing to preserve indentation
- 2.0.5
- Better highlighting of metadata (both YAML and MMD)
- 2.0.4
- False MMD metadata detection
- 2.0.0
- Rely on Redcarpet for Markdown parsing, far more accurate with a few losses I’ll handle over time
- Config file at ~/.config/mdless/config.yml
- Allow inlining of footnotes
- Nested list indentation
- 1.0.37
- Comments inside of fenced code rendering as ATX headlines
- 1.0.35
- Improved code block parsing and handling
- 1.0.33
- Allow multiple sections with
-s 3,4,5
- 1.0.32
- Errors in Ruby 3.2
- 1.0.30
- Errant pager output
- 1.0.29
- Allow $ markers for equations
- Don’t force white foreground when resetting color (allow default terminal color to be foreground
- Reset color properly when span elements are used in list items
- Code block border wrapping
- Use template settings for all footnote highlights
- Errant pager output1.0.13
- Fix for tables being eaten at the end of a document
- 1.0.10
- Fix for regex characters in headlines breaking rendering
- 1.0.9
- Catch error when breaking pipe
- 1.0.8
- Improved table formatting
- 1.0.7
- Force rewrite of damaged themes
- Add iTerm marks to h1-3 when using iTerm and no pager, so you can navigate with ⌘⇧↑/↓
- 1.0.6
- Fresh theme write was outputting
--- default
instead of a theme - Better code span color
- If
bat
is the pager, force into--plain
mode - 1.0.5
- Stop adjusting for highest header
- 1.0.3
- Sort options order in
--help
output - Allow multiple theme files,
--theme=NAME
option - 1.0.2
- Handle emphasis inside of quotes and parenthesis
- Make emphasis themeable in mdless.theme
- Fix for
-I
throwing error if imgcat isn’t installed - remove backslash from escaped characters
- 1.0.1
- Fix for header listing justification
- Exclude horizontal rules
---
in header list - 1.0.0
- Just a version bump because I think it deserves it at this point.
- 0.0.15
- User themeable
- Handle Setex headers
- General fixes and improvements
- 0.0.14
- Don’t run pygments on code blocks without language specified in either the fence or a hashbang on the first line
- Fix to maintain indentation for fenced code in lists
- Remove leading ~ for code blocks
- Add background color
- Add line ending marker to make more sense of code wrapping
- lowercase code block fences
- remove “end code” marker
- Highlight with monokai theme
- Black background for all (fenced) code blocks
- 0.0.13
- Better language detection for code blocks
- when available, use italic font for italics and bold-italics emphasis
- new colorization for html tags
Speaking of mdless…