HAL 0.3.10: 텍스트 셸 복사 대응 — 출력에서 인증 주소 자동 추출(줄 끝에서 끊긴 긴 주소 이어 붙임, 스크롤백·대체 화면 포함)과 "감지된 주소" 복사·열기 단추, 단말 드래그 선택 시 Ctrl+C 는 복사(Ctrl+Shift+C 항상 복사, 선택 없을 때만 셸로 전송), 전체 출력 복사·선택 복사·텍스트로 보기, 클립보드 폴백, 셸 모달 순수 템플릿화, 개발 지시 v0.3.10(Oz)·docs/HAL-AI.md §9·VERSION_HISTORY 0.3.10 — test/hal-ai-0310.test.mjs RED 0/4 → GREEN 4/4, 전체 29파일 199건 통과
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -76,3 +76,29 @@ export function keyToBytes(e) {
|
||||
const map = { Enter: '\r', Backspace: '\x7f', Tab: '\t', Escape: '\x1b', ArrowUp: '\x1b[A', ArrowDown: '\x1b[B', ArrowRight: '\x1b[C', ArrowLeft: '\x1b[D', Home: '\x1b[H', End: '\x1b[F', Delete: '\x1b[3~', PageUp: '\x1b[5~', PageDown: '\x1b[6~', Insert: '\x1b[2~' };
|
||||
if (map[k]) return map[k]; if (k.length === 1 && !ctrl && !e.altKey) return k; return null;
|
||||
}
|
||||
|
||||
/** [0.3.10] 스크롤백 + 화면의 모든 줄. 줄이 꽉 찬 경우(열 수만큼) 다음 줄과 이어진 것으로 보고 붙인다(긴 주소가 줄 끝에서 끊긴 경우). */
|
||||
export function joinedLines(term) {
|
||||
const raw = [...term.scrollback(), ...term.grid.map((r) => r.join(''))].map((l) => l.replace(/\s+$/, ''));
|
||||
const out = []; let cur = null;
|
||||
for (const l of raw) { if (cur === null) cur = l; else cur += l; if (cur.length > 0 && l.length === term.cols) continue; out.push(cur); cur = null; }
|
||||
if (cur !== null) out.push(cur); return out;
|
||||
}
|
||||
/** [0.3.10] 복사·붙여넣기용 전체 글(이어 붙인 줄 기준) */
|
||||
export const plainText = (term) => joinedLines(term).join('\n');
|
||||
const URL_RE = /https?:\/\/[^\s<>"'`│┃║|]+/g;
|
||||
/** [0.3.10] 출력에 나온 주소(중복 제거, 순서 유지). 꼬리 구두점은 뗀다. */
|
||||
export function extractUrls(term) {
|
||||
const seen = new Set(); const out = [];
|
||||
for (const line of joinedLines(term)) for (const m of line.matchAll(URL_RE)) { const u = m[0].replace(/[.,;:!?)\]}'"]+$/, ''); if (u.length > 10 && !seen.has(u)) { seen.add(u); out.push(u); } }
|
||||
return out;
|
||||
}
|
||||
/** [0.3.10] 단말 영역의 키 처리: 'copy'(브라우저 복사에 맡김) · 'paste'(클립보드 붙여넣기) · 'send'(셸로 전송). 선택된 글이 있으면 Ctrl+C 는 복사. */
|
||||
export function copyDecision(e, hasSelection) {
|
||||
const k = String(e.key || '').toLowerCase(); const ctrl = !!(e.ctrlKey || e.metaKey);
|
||||
if (ctrl && k === 'insert') return 'copy';
|
||||
if (ctrl && k === 'c') return e.shiftKey || hasSelection ? 'copy' : 'send';
|
||||
if (ctrl && k === 'v') return 'paste';
|
||||
if (e.shiftKey && k === 'insert') return 'paste';
|
||||
return 'send';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user