代码编辑器多光标实现技术详解
1. 多光标核心概念
多光标(Multiple Cursors)允许用户在同一时间内对多个位置进行编辑,是现代编辑器(VS Code、Sublime Text、Atom)的核心功能。
主要类型包括:
- 多选区(Multiple Selections):每个选区有独立的起始和结束位置
- 列模式(Column Selection):在多行同一列位置创建光标
- 增加选区(Add Selection):Ctrl+D 逐个添加当前词的选区
2. 数据结构设计
/* 多选区管理器核心结构 */
typedef struct Selection {
size_t start; /* 选区起始位置(字符偏移) */
size_t end; /* 选区结束位置 */
int cursor; /* 主光标位置(用于方向键导航) */
int anchor; /* 锚点位置(shift+点击时固定端) */
} Selection;
typedef struct SelectionManager {
Selection *selections; /* 选区数组 */
int count; /* 选区数量 */
int primary; /* 主选区索引(键盘操作以它为准) */
} SelectionManager;
3. 创建多光标的方式
3.1 Ctrl+D 添加选区
选中当前词后,按 Ctrl+D 会查找文档中相同的词并逐个添加为选区。
/* 添加下一个匹配选区 */
void add_next_selection(Editor *ed) {
char *word = get_selection_text(ed, ed->sel.primary);
if (!word) return;
size_t pos = find_next(ed->text, ed->sel.selections[ed->sel.primary].end, word);
if (pos != NULL) {
add_selection(&ed->sel, pos, pos + strlen(word));
}
free(word);
}
3.2 Alt+鼠标点击
按住 Alt 点击可以在任意位置创建新光标。
/* Alt+Click 创建新光标 */
void handle_alt_click(Editor *ed, int x, int y) {
size_t pos = coords_to_offset(ed, x, y);
/* 检查该位置是否已存在选区 */
for (int i = 0; i < ed->sel.count; i++) {
if (pos >= ed->sel.selections[i].start &&
pos <= ed->sel.selections[i].end) {
return; /* 已有选区,不重复创建 */
}
}
add_selection(&ed->sel, pos, pos);
}
3.3 列模式选择
/* Alt+拖拽创建列选区 */
void add_column_selection(Editor *ed, int start_y, int end_y, int col) {
int start_row = y_to_row(ed, start_y);
int end_row = y_to_row(ed, end_y);
for (int r = start_row; r <= end_row; r++) {
size_t line_start = get_line_start(ed, r);
size_t line_end = get_line_end(ed, r);
size_t pos = line_start + col;
if (pos < line_end) {
add_selection(&ed->sel, pos, pos);
}
}
}
4. 多光标编辑逻辑
多光标编辑的核心是对所有选区执行相同的编辑操作。
/* 多光标插入文本 */
void multi_insert(Editor *ed, const char *text) {
/* 按位置倒序排序,避免编辑后位置偏移 */
sort_selections_by_position(&ed->sel, 1);
for (int i = 0; i < ed->sel.count; i++) {
size_t pos = ed->sel.selections[i].start;
insert_text(&ed->text, pos, text);
/* 更新后续选区位置 */
size_t len = strlen(text);
for (int j = i + 1; j < ed->sel.count; j++) {
ed->sel.selections[j].start += len;
ed->sel.selections[j].end += len;
}
}
}
5. 视觉指示器实现
- 光标渲染:每个选区都有独立的光标竖线
- 选区高亮:不同选区可以使用不同颜色或统一背景色
- 线条指示:主选区可通过更亮的颜色或边框区分
/* 渲染多光标(CSS/Canvas 示例) */
/* 主选区 - 更亮的颜色 */
.cursor.primary { background: #34d399; }
/* 副选区 - 半透明 */
.cursor.secondary { background: rgba(52,211,153,0.6); }
/* 选区背景 */
.selection {
background: rgba(52,211,153,0.25);
border-radius: 2px;
}
实现要点:多光标编辑的关键是(1)正确的数据结构管理多个选区;(2)编辑操作对所有选区应用;(3)位置排序防止编辑后偏移;(4)视觉上清晰区分主副选区。