✨ feat(vscode): 代码阅读库规则卡片不再吞掉字段中间的方法,编辑时收起子块
This commit is contained in:
1 parent
c803fd457f
commit
2251e67ef8
15 files changed
+280
-54
No files matched your search
@@ -0,0 +1,51 @@
|
||||
import type { BlockView } from './types'
|
||||
|
||||
/**
|
||||
* 同一时刻能编辑的几段源码不重叠,同一行不会同时在两处能改:
|
||||
* ① 块编辑时,编辑范围和它重叠的子孙块不画(库规则的卡片编辑整个类,留下的方法也在这段里;
|
||||
* 一行写完的 `if x: return 1`,子块和头部在同一行),它们下面的子孙也跟着不画;
|
||||
* ② 点「编辑」时,编辑范围和这块重叠的别的块退出编辑。
|
||||
*/
|
||||
|
||||
type Lines = Pick<BlockView, 'startLine' | 'endLine'>
|
||||
|
||||
function overlaps(a: Lines, b: Lines): boolean {
|
||||
return a.startLine <= b.endLine && b.startLine <= a.endLine
|
||||
}
|
||||
|
||||
/** 正在编辑的块盖住、不画的块 → 盖住它的那块(页面上画着的、正在编辑的祖先):跳到定义落在被盖住的块上时改闪它。 */
|
||||
export function coveredByEditing(blocks: readonly BlockView[], editing: ReadonlySet<string>): Map<string, string> {
|
||||
const covered = new Map<string, string>()
|
||||
const visit = (list: readonly BlockView[], editors: readonly BlockView[], owner: string | undefined): void => {
|
||||
for (const block of list) {
|
||||
const by = owner ?? editors.find(editor => overlaps(editor, block))?.id
|
||||
if (by !== undefined) {
|
||||
covered.set(block.id, by)
|
||||
visit(block.children, editors, by)
|
||||
}
|
||||
else {
|
||||
visit(block.children, editing.has(block.id) ? [...editors, block] : editors, undefined)
|
||||
}
|
||||
}
|
||||
}
|
||||
visit(blocks, [], undefined)
|
||||
return covered
|
||||
}
|
||||
|
||||
function* allBlocks(blocks: readonly BlockView[]): Generator<BlockView> {
|
||||
for (const block of blocks) {
|
||||
yield block
|
||||
yield* allBlocks(block.children)
|
||||
}
|
||||
}
|
||||
|
||||
/** 点了 id 这块的「编辑」之后正在编辑的块:加上它,编辑范围和它重叠的别的块退出编辑。 */
|
||||
export function startEditing(blocks: readonly BlockView[], editing: readonly string[], id: string): string[] {
|
||||
const byId = new Map([...allBlocks(blocks)].map(block => [block.id, block]))
|
||||
const target = byId.get(id)
|
||||
const others = editing.filter((other) => {
|
||||
const block = byId.get(other)
|
||||
return other !== id && !(target && block && overlaps(target, block))
|
||||
})
|
||||
return [...others, id]
|
||||
}
|
||||
Reference in new issue
Block a user