qwen-code/docs/users/features/markdown-rendering.md
顾盼 21a40bd74a
feat(cli): support /copy N to copy Nth-last AI message (#4761)
* feat(cli): support /copy N to copy Nth-last AI message

Lets users grab earlier AI replies without scrolling — `/copy 2` copies
the second-to-last AI message, `/copy 3 code python` extracts the last
Python code block from the third-to-last, etc. Useful when the agent's
final action is something low-signal (TODO update, status line) and the
substantive output is one or two turns back.

The arg parser strips a leading positive-integer token and treats it as
a 1-based message index (1 = last AI message); the remaining tokens are
passed unchanged to the existing code/LaTeX sub-selectors. `/copy code
python 2` keeps its prior meaning (2nd python block in last message)
because its leading token isn't a digit.

Closes #4744

* feat(cli): add argumentHint for /copy so completion menu shows syntax

* feat(cli): simplify /copy argumentHint to [N], add four-component regression test

Claude Code's /copy only exposes N as an arg ("Copy Claude's last response
to clipboard (or /copy N for the Nth-latest)"); block selection happens in
a UI picker, not via command syntax. Aligning the hint with that — the
existing code/latex/<lang>/<index> sub-selectors still work but they were
never advertised in a hint before and double-numeric "[N] … [<index>]"
was confusing.

Also lock in /copy 3 code python 2 (message-index + code + lang +
within-message block-index) as a regression test, since that combo was
not previously asserted.

* feat(cli): inline /copy N hint in description across all 9 locales

The `[N]` argumentHint alone is opaque — users see "[N]" in the
completion menu but the description "Copy the last result or code
snippet to clipboard" never says what N does. Claude Code's /copy
solves this by inlining the hint in the description itself: "Copy
Claude's last response to clipboard (or /copy N for the Nth-latest)".

Mirror that pattern. The i18n key is the English source string, so
all 9 locale files (en/zh/zh-TW/de/fr/pt/ca/ru/ja) must update both
the key and the localized value to avoid orphaning translations and
falling back to English. Translated each one to keep parity.

Also drop "or code snippet" — code/latex sub-selection is a secondary
feature documented in docs/users/features/markdown-rendering.md, and
Claude Code's reference UX doesn't mention it in the description.

* fix(cli): /copy N — N-aware result wording, rename _args, polish de translation

Three review findings from a self-review pass:

1. Result strings hardcoded "last AI output" / "Last output copied" even
   when the user explicitly addressed an earlier message via /copy N. A
   user running `/copy 3 code` previously got "No matching code block
   found in the last AI output." — but they didn't ask about the last,
   they asked about the 3rd-last. Source label now branches on N:
   N=1 / no-N keep the original "last AI output" / "Last output copied"
   wording (tests stable); N>1 reads "AI message N". Covers the three
   "found in" error strings, the "contains no text to copy" branch,
   and the full-message success label. New tests assert the AI-message-N
   wording in the no-text and selector-miss cases.

2. The action handler signature still used `_args` (underscore-prefix
   indicates an unused parameter), but the body now reads from it via
   `parseLeadingMessageIndex(_args)`. Rename to `args` so the convention
   matches actual usage and other commands in this directory.

3. de translation `N-letzte` floats grammatically (adjective without a
   head noun); native speakers understand it but it reads clipped. Add
   the missing article: `für die N-letzte`.
2026-06-08 10:08:45 +08:00

183 lines
8.4 KiB
Markdown

# Markdown Rendering
Qwen Code renders common Markdown structures directly in the TUI so model
answers are easier to scan without leaving the terminal. The renderer is
designed to keep the original source reachable, especially for visual blocks
such as Mermaid diagrams and LaTeX math.
## Render and Raw Modes
By default, Markdown is shown in `render` mode. Supported blocks render as
visual previews where possible:
- Mermaid fenced code blocks
- Markdown tables
- task lists
- blockquotes
- inline and block LaTeX math
- fenced code blocks with syntax highlighting
Press `Alt/Option+M` to toggle the current session between modes. On macOS,
the terminal must send Option as Meta for this shortcut; otherwise Option+M is
treated as normal text input.
- `render`: show rich terminal previews for supported Markdown.
- `raw`: show source-oriented Markdown for visual blocks such as Mermaid,
tables, and LaTeX.
To start Qwen Code in raw mode by default, set `ui.renderMode`:
```json
{
"ui": {
"renderMode": "raw"
}
}
```
Accepted values are `"render"` and `"raw"`. The shortcut only changes the
current session view; it does not rewrite your settings file.
## Mermaid
Fenced `mermaid` code blocks render visually in `render` mode. The TUI uses a
layered strategy:
1. If enabled and supported, Qwen Code asks Mermaid CLI (`mmdc`) to render the
diagram to a PNG and sends it to the terminal image protocol.
2. If terminal images are unavailable but `chafa` is installed, the same PNG can
be converted to ANSI block graphics.
3. Otherwise, Qwen Code falls back to a terminal wireframe or compact text
preview.
4. If a Mermaid diagram type cannot be previewed, Qwen Code shows the original
fenced source instead of hiding it behind a placeholder.
Mermaid image rendering is disabled by default because it requires external
renderers and terminal image support. Enable it with:
```bash
QWEN_CODE_MERMAID_IMAGE_RENDERING=1 qwen
```
Optional environment variables:
| Variable | Description |
| ------------------------------------------- | ----------------------------------------------------------------------------------- |
| `QWEN_CODE_MERMAID_IMAGE_RENDERING=1` | Enables external Mermaid image rendering. |
| `QWEN_CODE_DISABLE_MERMAID_IMAGES=1` | Disables Mermaid image rendering even when enabled elsewhere. |
| `QWEN_CODE_MERMAID_IMAGE_PROTOCOL=kitty` | Forces Kitty protocol output. Useful for terminals such as Kitty and Ghostty. |
| `QWEN_CODE_MERMAID_IMAGE_PROTOCOL=iterm2` | Requests iTerm2 inline images. Interactive TUI rendering falls back to text/ANSI. |
| `QWEN_CODE_MERMAID_IMAGE_PROTOCOL=off` | Disables terminal image protocols and allows text or `chafa` fallback. |
| `QWEN_CODE_MERMAID_MMD_CLI=/path/to/mmdc` | Uses a specific Mermaid CLI executable. |
| `QWEN_CODE_MERMAID_ALLOW_NPX=1` | Allows Qwen Code to run `npx @mermaid-js/mermaid-cli` when `mmdc` is not installed. |
| `QWEN_CODE_MERMAID_ALLOW_LOCAL_RENDERERS=1` | Allows project-local renderer binaries under `node_modules/.bin`. |
| `QWEN_CODE_MERMAID_RENDER_WIDTH=1200` | Overrides the PNG render width. |
| `QWEN_CODE_MERMAID_RENDER_TIMEOUT_MS=10000` | Overrides the external render timeout, capped at 60000 ms. |
| `QWEN_CODE_MERMAID_CELL_ASPECT_RATIO=0.5` | Adjusts image row fitting for terminal font cell geometry. |
The first image render can be slow, especially when `npx` needs to resolve or
download Mermaid CLI. During streaming, Qwen Code shows a bounded text preview
and attempts image rendering only after the model response is complete.
### Mermaid Source Copy
Every rendered Mermaid block includes a source hint such as:
```text
Mermaid flowchart (TD) · source: /copy mermaid 1
```
Use these commands to copy Mermaid source from the last AI response:
| Command | Behavior |
| ---------------------- | --------------------------------------------- |
| `/copy mermaid` | Copies the last Mermaid block. |
| `/copy mermaid 1` | Copies the first Mermaid block. |
| `/copy code mermaid` | Copies the last fenced `mermaid` code block. |
| `/copy code mermaid 1` | Copies the first fenced `mermaid` code block. |
`/copy code 1` counts all fenced code blocks, not only Mermaid blocks. Use
`/copy mermaid N` when you want the Mermaid-specific sequence shown in the
rendered title.
## LaTeX Math
Qwen Code supports basic inline and block LaTeX rendering in the terminal:
```markdown
Inline math: $x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$
$$
\sum_{n=1}^{\infty} 1/n^2 = \pi^2/6
$$
```
The renderer focuses on common symbols and readable terminal output. It is not
a full TeX engine; complex layouts such as matrices, aligned equations, and
large nested expressions may be simplified.
Inline `$...$` expressions are intentionally bounded to 1024 characters per
line so malformed or very large generated Markdown cannot stall terminal
rendering. Longer formulas remain visible as source text and can still be
copied from raw mode or the original response.
### LaTeX Source Copy
Use these commands to copy LaTeX source from the last AI response:
| Command | Behavior |
| ---------------------- | --------------------------------------- |
| `/copy latex` | Copies the last block LaTeX expression. |
| `/copy latex 2` | Copies the second block expression. |
| `/copy latex inline` | Copies the last inline expression. |
| `/copy latex inline 2` | Copies the second inline expression. |
| `/copy inline-latex 2` | Alias for `/copy latex inline 2`. |
Inline LaTeX does not show a per-expression copy hint in rendered text to avoid
making prose noisy. Switch to raw mode with `Alt/Option+M` when you want to
inspect inline source in place; on macOS this requires Option-as-Meta terminal
input.
## General Code Copy
The `/copy code` command reads fenced code blocks from the last AI Markdown
response:
| Command | Behavior |
| ----------------------- | ---------------------------------------- |
| `/copy code` | Copies the last fenced code block. |
| `/copy code 2` | Copies the second fenced code block. |
| `/copy code typescript` | Copies the last `typescript` code block. |
| `/copy code mermaid 1` | Copies the first `mermaid` code block. |
## Selecting an Earlier AI Message
By default `/copy` targets the most recent AI message. Prefix the command with
a positive integer to copy from the Nth-last AI message instead — handy when
the latest reply is something low-signal (e.g., a TODO update) and the
substantive output is one or two turns back.
| Command | Behavior |
| --------------------- | ------------------------------------------------------ |
| `/copy 2` | Copies the second-to-last AI message in full. |
| `/copy 3` | Copies the third-to-last AI message in full. |
| `/copy 2 code python` | Copies the last `python` code block from the 2nd-last. |
| `/copy 3 latex` | Copies the last LaTeX block from the 3rd-last message. |
`/copy 1` is equivalent to `/copy`. If `N` exceeds the number of AI messages
in the session, `/copy` reports the actual count instead of copying anything.
Without a leading integer, sub-selectors such as `/copy code python 2` keep
their existing meaning (the 2nd `python` block in the last message).
## Current Limits
- Mermaid image rendering depends on Mermaid CLI plus terminal image support.
- Async iTerm2 inline image placement is disabled in the TUI because the
protocol is cursor-position bound; use Kitty/Ghostty or ANSI fallback for
interactive image previews.
- Wireframe Mermaid rendering is a readable terminal preview, not a full
Mermaid layout engine.
- Raw mode is global for rendered Markdown blocks; it is not a per-block toggle.
- LaTeX rendering covers common symbols and expressions, not full TeX layout.
- Source copy commands target the last AI response by default, or the Nth-last
when invoked as `/copy N ...`.