docs: Rewrite README as Unix man page, remove Chinese comments

Following Unix philosophy and documentation standards:
- Rewrite README.md in man page format (NAME, SYNOPSIS, DESCRIPTION, etc.)
- Remove all Chinese comments from source code
- Keep code clean and self-documenting
- Add PHILOSOPHY section explaining Unix principles
- Include proper EXIT STATUS, ENVIRONMENT, and FILES sections
- Reference related tools in SEE ALSO section
This commit is contained in:
m1ngsama 2025-12-08 16:11:39 +08:00
parent 818f5ddc5e
commit 354133b500
7 changed files with 203 additions and 248 deletions

459
README.md
View file

@ -1,263 +1,256 @@
# TUT - Terminal User Interface Browser
TUT(1) - Terminal User Interface Browser
========================================
一个专注于阅读体验的终端网页浏览器采用vim风格的键盘操作让你在终端中舒适地浏览网页文本内容。
NAME
----
tut - vim-style terminal web browser
## 特性
SYNOPSIS
--------
**tut** [*URL*]
- 🚀 **纯文本浏览** - 专注于文本内容,无图片干扰
- ⌨️ **完全vim风格操作** - hjkl移动、gg/G跳转、/搜索等
- 📖 **报纸式排版** - 自适应宽度居中显示,优化阅读体验
- 🔗 **链接导航** - TAB键切换链接Enter跟随链接
- 📜 **历史管理** - h/l快速前进后退
- 🎨 **优雅配色** - 精心设计的终端配色方案
- 🔍 **内容搜索** - 支持文本搜索和高亮
**tut** **-h** | **--help**
## 依赖
DESCRIPTION
-----------
**tut** is a text-mode web browser designed for comfortable reading in the
terminal. It extracts and displays the textual content of web pages with a
clean, centered layout optimized for reading, while providing vim-style
keyboard navigation.
- CMake ≥ 3.15
- C++17 编译器macOS 建议 clangLinux 建议 g++
- `ncurses``ncursesw`(支持宽字符)
- `libcurl`支持HTTPS
The browser does not execute JavaScript or display images. It is designed
for reading static HTML content, documentation, and text-heavy websites.
### macOS (Homebrew) 安装依赖
OPTIONS
-------
*URL*
Open the specified URL on startup. If omitted, displays the built-in
help page.
**-h**, **--help**
Display usage information and exit.
KEYBINDINGS
-----------
**tut** uses vim-style keybindings throughout.
### Navigation
**j**, **Down**
Scroll down one line.
**k**, **Up**
Scroll up one line.
**Ctrl-D**, **Space**
Scroll down one page.
**Ctrl-U**, **b**
Scroll up one page.
**gg**
Jump to top of page.
**G**
Jump to bottom of page.
**[***count***]G**
Jump to line *count* (e.g., **50G** jumps to line 50).
**[***count***]j**, **[***count***]k**
Scroll down/up *count* lines (e.g., **5j** scrolls down 5 lines).
### Link Navigation
**Tab**
Move to next link.
**Shift-Tab**, **T**
Move to previous link.
**Enter**
Follow current link.
**h**, **Left**
Go back in history.
**l**, **Right**
Go forward in history.
### Search
**/**
Start search. Enter search term and press **Enter**.
**n**
Jump to next search match.
**N**
Jump to previous search match.
### Commands
Press **:** to enter command mode. Available commands:
**:q**, **:quit**
Quit the browser.
**:o** *URL*, **:open** *URL*
Open *URL*.
**:r**, **:refresh**
Reload current page.
**:h**, **:help**
Display help page.
**:***number*
Jump to line *number*.
### Other
**r**
Reload current page.
**q**
Quit the browser.
**?**
Display help page.
**ESC**
Cancel command or search input.
LIMITATIONS
-----------
**tut** does not execute JavaScript. Modern single-page applications (SPAs)
built with React, Vue, Angular, or similar frameworks will not work correctly,
as they require JavaScript to render content.
To determine if a site will work with **tut**, use:
curl https://example.com | less
If you can see the actual content in the HTML source, the site will work.
If you only see JavaScript code or empty div elements, it will not.
Additionally:
- No image display
- No CSS layout support
- No form submission
- No cookie or session management
- No AJAX or dynamic content loading
EXAMPLES
--------
View the built-in help:
tut
Browse Hacker News:
tut https://news.ycombinator.com
Read Wikipedia:
tut https://en.wikipedia.org/wiki/Unix_philosophy
Open a URL, search for "unix", and navigate:
tut https://example.com
/unix<Enter>
n
DEPENDENCIES
------------
- ncurses or ncursesw (for terminal UI)
- libcurl (for HTTPS support)
- CMake >= 3.15 (build time)
- C++17 compiler (build time)
INSTALLATION
------------
### From Source
**macOS (Homebrew):**
```bash
brew install cmake ncurses curl
```
### Linux (Ubuntu/Debian) 安装依赖
```bash
sudo apt-get update
sudo apt-get install build-essential cmake libncursesw5-dev libcurl4-openssl-dev
```
### Linux (Fedora/RHEL) 安装依赖
```bash
sudo dnf install cmake gcc-c++ ncurses-devel libcurl-devel
```
## 构建
在项目根目录执行:
```bash
mkdir -p build
cd build
mkdir -p build && cd build
cmake ..
cmake --build .
```
sudo install -m 755 tut /usr/local/bin/
生成的可执行文件为 `tut`
**Linux (Debian/Ubuntu):**
## 运行
sudo apt-get install cmake libncursesw5-dev libcurl4-openssl-dev
mkdir -p build && cd build
cmake ..
cmake --build .
sudo install -m 755 tut /usr/local/bin/
### 直接启动(显示帮助页面)
**Linux (Fedora/RHEL):**
```bash
./tut
```
sudo dnf install cmake gcc-c++ ncurses-devel libcurl-devel
mkdir -p build && cd build
cmake ..
cmake --build .
sudo install -m 755 tut /usr/local/bin/
### 打开指定URL
### Using Makefile
```bash
./tut https://example.com
./tut https://news.ycombinator.com
```
make
sudo make install
### 显示使用帮助
FILES
-----
No configuration files are used. The browser is stateless and does not
store history, cookies, or cache.
```bash
./tut --help
```
ENVIRONMENT
-----------
**tut** respects the following environment variables:
## 键盘操作
**TERM**
Terminal type. Must support basic cursor movement and colors.
### 导航
**LINES**, **COLUMNS**
Terminal size. Automatically detected via ncurses.
| 按键 | 功能 |
|------|------|
| `j` / `↓` | 向下滚动一行 |
| `k` / `↑` | 向上滚动一行 |
| `Ctrl-D` / `Space` | 向下翻页 |
| `Ctrl-U` / `b` | 向上翻页 |
| `gg` | 跳转到顶部 |
| `G` | 跳转到底部 |
| `[数字]G` | 跳转到指定行(如 `50G` |
| `[数字]j/k` | 向下/上滚动指定行数(如 `5j` |
EXIT STATUS
-----------
**0**
Success.
### 链接操作
**1**
Error occurred (e.g., invalid URL, network error, ncurses initialization
failure).
| 按键 | 功能 |
|------|------|
| `Tab` | 下一个链接 |
| `Shift-Tab` / `T` | 上一个链接 |
| `Enter` | 跟随当前链接 |
| `h` / `←` | 后退 |
| `l` / `→` | 前进 |
PHILOSOPHY
----------
**tut** follows the Unix philosophy:
### 搜索
1. Do one thing well: display and navigate text content from the web.
2. Work with other programs: output can be piped, URLs can come from stdin.
3. Simple and minimal: no configuration files, no persistent state.
4. Text-focused: everything is text, processed and displayed cleanly.
| 按键 | 功能 |
|------|------|
| `/` | 开始搜索 |
| `n` | 下一个匹配 |
| `N` | 上一个匹配 |
The design emphasizes keyboard efficiency, clean output, and staying out
of your way.
### 命令模式
SEE ALSO
--------
lynx(1), w3m(1), curl(1), vim(1)
`:` 进入命令模式,支持以下命令:
BUGS
----
Report bugs at: https://github.com/m1ngsama/TUT/issues
| 命令 | 功能 |
|------|------|
| `:q` / `:quit` | 退出浏览器 |
| `:o URL` / `:open URL` | 打开指定URL |
| `:r` / `:refresh` | 刷新当前页面 |
| `:h` / `:help` | 显示帮助 |
| `:[数字]` | 跳转到指定行 |
AUTHORS
-------
m1ngsama <contact@m1ng.space>
### 其他
| 按键 | 功能 |
|------|------|
| `r` | 刷新当前页面 |
| `q` | 退出浏览器 |
| `?` | 显示帮助 |
| `ESC` | 取消命令/搜索输入 |
## 使用示例
### 浏览新闻网站
```bash
./tut https://news.ycombinator.com
```
然后:
- 使用 `j/k` 滚动浏览标题
- 按 `Tab` 切换到感兴趣的链接
- 按 `Enter` 打开链接
- 按 `h` 返回上一页
### 阅读文档
```bash
./tut https://en.wikipedia.org/wiki/Unix
```
然后:
- 使用 `gg` 跳转到顶部
- 使用 `/` 搜索关键词(如 `/history`
- 使用 `n/N` 在搜索结果间跳转
- 使用 `Space` 翻页阅读
### 快速查看多个网页
```bash
./tut https://github.com
```
在浏览器内:
- 浏览页面并点击链接
- 使用 `:o https://news.ycombinator.com` 打开新URL
- 使用 `h/l` 在历史中前进后退
## 设计理念
TUT 的设计目标是提供最佳的终端阅读体验:
1. **极简主义** - 只关注文本内容,摒弃图片、广告等干扰元素
2. **高效操作** - 完全键盘驱动,无需触摸鼠标
3. **优雅排版** - 自适应宽度,居中显示,类似专业阅读器
4. **快速响应** - 轻量级实现,即开即用
## 架构
```
TUT
├── http_client - HTTP/HTTPS 网页获取
├── html_parser - HTML 解析和文本提取
├── text_renderer - 文本渲染和排版引擎
├── input_handler - Vim 风格输入处理
└── browser - 浏览器主循环和状态管理
```
## 限制
### JavaScript/SPA 网站
**重要:** 这个浏览器**不支持JavaScript执行**。这意味着:
- ❌ **不支持**单页应用(SPA)React、Vue、Angular、Astro等构建的现代网站
- ❌ **不支持**动态内容加载
- ❌ **不支持**AJAX请求
- ❌ **不支持**客户端路由
**如何判断网站是否支持:**
1. 用 `curl` 命令查看HTML内容`curl https://example.com | less`
2. 如果能看到实际的文章内容则支持如果只有JavaScript代码或空白div则不支持
**你的网站示例:**
- ✅ **thinker.m1ng.space** - 静态HTML完全支持可以浏览文章列表并点击进入具体文章
- ❌ **blog.m1ng.space** - 使用Astro SPA构建内容由JavaScript动态渲染无法正常显示
**替代方案:**
- 对于SPA网站查找是否有RSS feed或API端点
- 使用服务器端渲染(SSR)版本的URL如果有
- 寻找使用传统HTML构建的同类网站
### 其他限制
- 不支持图片显示
- 不支持复杂的CSS布局
- 不支持表单提交
- 不支持Cookie和会话管理
- 专注于内容阅读,不适合需要交互的网页
## 开发指南
### 代码风格
- 遵循 C++17 标准
- 使用 RAII 进行资源管理
- 使用 Pimpl 模式隐藏实现细节
### 测试
```bash
cd build
./tut https://example.com
```
### 贡献
欢迎提交 Pull Request请确保
1. 代码风格与现有代码一致
2. 添加必要的注释
3. 测试新功能
4. 更新文档
## 版本历史
- **v1.0.0** - 完全重构为终端浏览器
- 添加 HTTP/HTTPS 支持
- 实现 HTML 解析
- 实现 Vim 风格操作
- 报纸式排版引擎
- 链接导航和搜索功能
- **v0.0.1** - 初始版本ICS 日历查看器)
## 许可证
MIT License
## 致谢
灵感来源于:
- `lynx` - 经典的终端浏览器
- `w3m` - 另一个优秀的终端浏览器
- `vim` - 最好的文本编辑器
- `btop` - 美观的TUI设计
Inspired by lynx, w3m, and vim.
LICENSE
-------
MIT License. See LICENSE file for details.

View file

@ -17,14 +17,12 @@ public:
std::vector<std::string> history;
int history_pos = -1;
// 视图状态
int scroll_pos = 0;
int current_link = -1;
std::string status_message;
std::string search_term;
std::vector<int> search_results; // 匹配行号
std::vector<int> search_results;
// 屏幕尺寸
int screen_height = 0;
int screen_width = 0;
@ -36,7 +34,7 @@ public:
noecho();
keypad(stdscr, TRUE);
curs_set(0);
timeout(0); // non-blocking
timeout(0);
getmaxyx(stdscr, screen_height, screen_width);
}
@ -311,7 +309,6 @@ public:
}
void scroll_to_link(int link_idx) {
// 查找链接在渲染行中的位置
for (size_t i = 0; i < rendered_lines.size(); ++i) {
if (rendered_lines[i].is_link && rendered_lines[i].link_index == link_idx) {
int visible_lines = screen_height - 2;
@ -406,7 +403,7 @@ void Browser::run(const std::string& initial_url) {
int ch = getch();
if (ch == ERR) {
napms(50); // 50ms sleep
napms(50);
continue;
}

View file

@ -13,13 +13,8 @@ public:
Browser();
~Browser();
// 启动浏览器(进入主循环)
void run(const std::string& initial_url = "");
// 加载URL
bool load_url(const std::string& url);
// 获取当前URL
std::string get_current_url() const;
private:

View file

@ -21,14 +21,14 @@ enum class ElementType {
struct Link {
std::string text;
std::string url;
int position; // 在文档中的位置用于TAB导航
int position;
};
struct ContentElement {
ElementType type;
std::string text;
std::string url; // 对于链接元素
int level; // 对于标题元素1-6
std::string url;
int level;
};
struct ParsedDocument {
@ -43,13 +43,8 @@ public:
HtmlParser();
~HtmlParser();
// 解析HTML并提取可读内容
ParsedDocument parse(const std::string& html, const std::string& base_url = "");
// 设置是否保留代码块
void set_keep_code_blocks(bool keep);
// 设置是否保留列表
void set_keep_lists(bool keep);
private:

View file

@ -19,16 +19,9 @@ public:
HttpClient();
~HttpClient();
// 获取网页内容
HttpResponse fetch(const std::string& url);
// 设置超时(秒)
void set_timeout(long timeout_seconds);
// 设置用户代理
void set_user_agent(const std::string& user_agent);
// 设置是否跟随重定向
void set_follow_redirects(bool follow);
private:

View file

@ -5,10 +5,10 @@
#include <memory>
enum class InputMode {
NORMAL, // 正常浏览模式
COMMAND, // 命令模式 (:)
SEARCH, // 搜索模式 (/)
LINK // 链接选择模式
NORMAL,
COMMAND,
SEARCH,
LINK
};
enum class Action {
@ -36,10 +36,10 @@ enum class Action {
struct InputResult {
Action action;
std::string text; // 用于命令、搜索、URL输入
int number; // 用于跳转行号、链接编号等
bool has_count; // 是否有数字前缀(如 5j
int count; // 数字前缀
std::string text;
int number;
bool has_count;
int count;
};
class InputHandler {
@ -47,19 +47,10 @@ public:
InputHandler();
~InputHandler();
// 处理单个按键
InputResult handle_key(int ch);
// 获取当前模式
InputMode get_mode() const;
// 获取当前输入缓冲(用于显示命令行)
std::string get_buffer() const;
// 重置状态
void reset();
// 设置状态栏消息回调
void set_status_callback(std::function<void(const std::string&)> callback);
private:

View file

@ -6,22 +6,20 @@
#include <memory>
#include <curses.h>
// 渲染后的行信息
struct RenderedLine {
std::string text;
int color_pair;
bool is_bold;
bool is_link;
int link_index; // 如果是链接,对应的链接索引
int link_index;
};
// 渲染配置
struct RenderConfig {
int max_width = 80; // 内容最大宽度
int margin_left = 0; // 左边距(居中时自动计算)
bool center_content = true; // 是否居中内容
int paragraph_spacing = 1; // 段落间距
bool show_link_indicators = true; // 是否显示链接指示器
int max_width = 80;
int margin_left = 0;
bool center_content = true;
int paragraph_spacing = 1;
bool show_link_indicators = true;
};
class TextRenderer {
@ -29,13 +27,8 @@ public:
TextRenderer();
~TextRenderer();
// 渲染文档到行数组
std::vector<RenderedLine> render(const ParsedDocument& doc, int screen_width);
// 设置渲染配置
void set_config(const RenderConfig& config);
// 获取当前配置
RenderConfig get_config() const;
private:
@ -43,7 +36,6 @@ private:
std::unique_ptr<Impl> pImpl;
};
// 颜色定义
enum ColorScheme {
COLOR_NORMAL = 1,
COLOR_HEADING1,
@ -57,5 +49,4 @@ enum ColorScheme {
COLOR_DIM
};
// 初始化颜色方案
void init_color_scheme();