121 lines
3.2 KiB
Markdown
121 lines
3.2 KiB
Markdown
# mach
|
||
|
||
A CLI tool that converts Markdown files to rich text and copies the result to your system clipboard.
|
||
Paste formatted text directly into emails, Slack messages, Google Docs, or any app that supports rich text.
|
||
|
||
## Installation
|
||
|
||
```bash
|
||
make build
|
||
# binary is at ./build/mach
|
||
|
||
# or install to /usr/local/bin:
|
||
bash install.sh
|
||
```
|
||
|
||
## Usage
|
||
|
||
```
|
||
mach <file> [flags]
|
||
```
|
||
|
||
Convert a Markdown file and copy to clipboard:
|
||
|
||
```bash
|
||
mach notes.md
|
||
```
|
||
|
||
Also display the RTF output in the terminal:
|
||
|
||
```bash
|
||
mach notes.md -d
|
||
```
|
||
|
||
Write an RTF file next to the input (e.g. `notes.md` → `notes.rtf`):
|
||
|
||
```bash
|
||
mach notes.md -o
|
||
```
|
||
|
||
Write to a specific path:
|
||
|
||
```bash
|
||
mach notes.md -o=/tmp/output.rtf
|
||
```
|
||
|
||
### Flags
|
||
|
||
| Flag | Description |
|
||
|------|-------------|
|
||
| `-i` | Input format (default: `md`) |
|
||
| `-t` | Output format (default: `rtf`) |
|
||
| `-o` | Output to file; `-o` derives path from input, `-o=path` writes to path |
|
||
| `-d` | Display converted text in terminal |
|
||
| `-v` | Print version |
|
||
|
||
### Config
|
||
|
||
Optional config file at `~/.config/mach/config.json`:
|
||
|
||
```json
|
||
{
|
||
"input_type": "md",
|
||
"output_type": "rtf"
|
||
}
|
||
```
|
||
|
||
Flag values override config values.
|
||
|
||
## Supported Markdown
|
||
|
||
- Headings (H1–H6)
|
||
- Bold, italic, strikethrough
|
||
- Inline code and fenced code blocks
|
||
- Ordered and unordered lists
|
||
- Task lists (`- [x]` / `- [ ]`)
|
||
- Blockquotes
|
||
- Links (rendered as clickable hyperlinks)
|
||
- Tables (GFM)
|
||
- Horizontal rules
|
||
- Images (rendered as `[image: alt text]` placeholder)
|
||
|
||
## Technical Details
|
||
|
||
### Conversion Pipeline
|
||
|
||
mach uses [goldmark](https://github.com/yuin/goldmark) to parse Markdown into an AST, then walks the tree with a custom renderer that emits RTF directly. There is no intermediate HTML-to-RTF conversion and no dependency on external tools like `textutil` or `pandoc`. The RTF renderer is pure Go.
|
||
|
||
For clipboard, a second pass converts the Markdown to HTML using goldmark's built-in HTML renderer. Both formats are placed on the clipboard so that every app gets the type it expects.
|
||
|
||
### Dependencies
|
||
|
||
- [goldmark](https://github.com/yuin/goldmark) — Markdown parser with GFM extensions
|
||
- [cobra](https://github.com/spf13/cobra) — CLI framework
|
||
- [viper](https://github.com/spf13/viper) — Config file management
|
||
|
||
### Clipboard: OS Differences
|
||
|
||
The clipboard is the only OS-specific code in the project. No build tags are used; the binary is cross-platform via a `runtime.GOOS` switch.
|
||
|
||
**macOS** — Uses a small Swift snippet executed via `swift -` that writes to `NSPasteboard`. Three pasteboard types are set:
|
||
|
||
| Type | Purpose |
|
||
|------|---------|
|
||
| `public.html` | Web apps (Slack, Gmail, Google Docs) |
|
||
| `public.rtf` | Native apps (TextEdit, Word, Pages) |
|
||
| `public.utf8-plain-text` | Plain text fallback (required by Electron apps like Slack) |
|
||
|
||
`pbcopy` is not used because it can only set plain text — it has no way to specify the pasteboard type.
|
||
|
||
**Linux** — Uses `xclip` to set clipboard content with `text/html` MIME type. `xclip` must be installed (`sudo apt install xclip`).
|
||
|
||
### Build
|
||
|
||
Version is stored in the `VERSION` file and injected at build time via ldflags:
|
||
|
||
```
|
||
go build -ldflags "-X mach/cmd.Version=$(cat VERSION)" -o build/mach .
|
||
```
|
||
|
||
The Makefile handles this automatically with `make build`.
|