Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Register is more than clipboard

Register is more than clipboard

Avatar for Satoru Kitaguchi

Satoru Kitaguchi

November 02, 2025

More Decks by Satoru Kitaguchi

Other Decks in Programming

Transcript

  1. © 2025 Third Intelligence Beyond human, beyond AI — towards

    a new form of intelligence. Not the human brain, nor conventional AI. Third Intelligence is an AI research and development company committed to creating a new form of intelligence and AGI. Beyond raw intellect, we aim to build AI that thinks, converses, acts, and grows like a human — paving the way for a future where AI enhances the lives of people everywhere. We welcome those eager to join us in the challenge of creating and utilizing a new kind of intelligence that does not yet exist in the world, all within a globally competitive R&D environment. To learn more, please contact us below. 2
  2. © 2025 Third Intelligence Satoru Kitaguchi Software Engineer at Third

    Intelligence 3 About Me ^?:github|x)\.com/satorunooshie/?$
  3. © 2025 Third Intelligence 1. Understanding Register Internals 2. Why

    Numbered Registers Fail You 3. Building a Safer, Intentional Editing Workflow 4. Beyond Basics: Expressions, Macros, and Tricks 5. Clipboard Deep Dive 6. From Understanding to Internalization Agenda 4
  4. © 2025 Third Intelligence 1. Understanding Register Internals 2. Why

    Numbered Registers Fail You 3. Building a Safer, Intentional Editing Workflow 4. Beyond Basics: Expressions, Macros, and Tricks 5. Clipboard Deep Dive 6. From Understanding to Internalization Agenda 5
  5. © 2025 Third Intelligence Register “0 Last yank Always updated

    on a yank (y), never on delete / change. “1-9 Deletion history (new→old) Updated on linewise or multiline deletes / changes. “1 gets the newest others shift down. “- Small delete (within one line) Used for small deletes / changes like cw, dw, or single-line visual deletes. “_ Black hole Discards content. Nothing is saved. “(unnamed) Implicit Target Points to the last written register. (“0, “1, or “- depending on operation) Register Roles Table Role Notes 6
  6. © 2025 Third Intelligence Within only one line → “-;

    multi-line → “1ˮ Operation How Operations Decide Their Register yy “0 (also updates “ ) Yank always updates “0ˮ (unless blackhole “_ is used) dd “1 (also updatesˮ; numbered registers rotate) cw “- (also updates “ ) Single-line, characterwise change → small-delete register ci} “1 (also updates “) Multi-line → numbered register visual delete (charwise) “- / “1 Target Register Notes visual delete (linewise v) “1 Always linewise; triggers numbered-register rotation visual delete (block ctrl-v) “- / “1 Single-line block → "-; multi-line block → "1" Linewise or multi-line deletes go into “1ˮ and shift “29ˮ. 7
  7. © 2025 Third Intelligence small delete register MCHAR Understanding Delete

    Behavior small path, same register Cmnd cw ciw motion type line cnt MCHAR triggers numbered rotation ci} MLINE1 note rgst 1 1 2 “- “- “1 from cursor → word end across lines or blank lines Range inner word 8
  8. © 2025 Third Intelligence How Vim handles Deletion if (oap->regname

    != '_') { // skip if blackhole "_ if (oap->motion_type == MLINE || oap->line_count > 1) shift_delete_registers(); // move "1→"2→... (rotation) else if (oap->line_count == 1 && oap->motion_type != MLINE) oap->regname = '-'; // mark small delete endif op_yank(oap, TRUE, FALSE); // actually write to register } https://github.com/vim/vim/blob/0124320c97b0fbbb44613f42fc1c34fee6181fc8/src/ops.c#L771L1133 9
  9. © 2025 Third Intelligence - Paste commands (p, P, gp,

    gP) never alter registers. - gp / gP only differ by cursor placement. - . repeats the change — it reuses, not re-yanks. Paste before cursor. Paste and Repeat — “pˮ, “gpˮ, and “.ˮ Command p P Does not change any register gp gP Same as P Paste before, moves cursor after the pasted text. Register Effect Behavior Does not change any register Same as p Paste after cursor. Uses the unnamed register (“) by default Paste after, moves cursor after the pasted text. 10
  10. © 2025 Third Intelligence How Operations Decide Their Register Itʼs

    not the command — itʼs the motion. Registers depend on how wide your edit spans. The unnamed register (") is always updated (unless using the blackhole "_) ✔ "0 is yank-only — never touched by delete or change. ✔ "1–9 rotate only on linewise or multi-line deletes. ✔ "- is for small (single-line) deletes/changes. ✔ Use "_ to avoid writing to any register at all. 11
  11. © 2025 Third Intelligence 1. Command handling (ops.c) → recognize

    d, c, etc. 2. Range determination (motion / count) 3. Backup / undo staging 4. Register writing logic (registers.c) → Decide: - small delete ("-) vs numbered shift ("1) - unnamed (") or named ("a) register → Write yanked text to the chosen register How Vim updates registers 5. Buffer mutation → actually remove or change text in the buffer 6. Post-processing → Update undo stack → Redraw screen → Trigger TextYankPost autocmd 12
  12. © 2025 Third Intelligence Content Info How Vim updates registers

    // Yank: always updates "0 and unnamed (unless blackhole) if (is_yank && reg != '_') { if (explicit_reg) save_to_register(reg, yanked_text); // e.g. "ay save_to_register('0', yanked_text); // last yank ("0) save_to_register('"', yanked_text); // unnamed (") return; } // Delete / Change: if (is_delete_or_change && reg != '_') { // 1) If an explicit register is given, write there first. // (Small-delete handling happens only for implicit cases.) if (explicit_reg) { save_to_register(reg, deleted_text); // e.g. "ad } // 2) If linewise / spans multiple lines / forced use of "1 → rotate numbered regs. if (motion_is_linewise || spans_multiple_lines || use_reg_one) { shift_numbered_registers(); // "9←…←"2←"1 save_to_register('1', deleted_text); // write to "1 } // 3) Otherwise (single-line, charwise) and no explicit reg → small delete. else if (!explicit_reg) { save_to_register('-', deleted_text); // small delete ("-) } // 4) Unnamed is always updated unless blackhole. save_to_register('"', deleted_text); // update (") return; } 13
  13. © 2025 Third Intelligence 1. Understanding Register Internals 2. Why

    Numbered Registers Fail You 3. Building a Safer, Intentional Editing Workflow 4. Beyond Basics: Expressions, Macros, and Tricks 5. Clipboard Deep Dive 6. From Understanding to Internalization Agenda 14
  14. © 2025 Third Intelligence Do you REALLY want to keep

    track of this? Memorization Table Register “0 aaa (yank) “1 ccc (delete) “2 bbb (delete) “- xxx (small delete) Contents (after some edits) 15
  15. © 2025 Third Intelligence You didnʼt lose your yank. You

    just buried it under another register. “0 still holds line 1 — but p refers to “- 😢 Step 1 yy on line 1 "0, " ← line 1 2 3 cwfoo<Esc> 4 Pastes “-” instead of “0 5 :reg Operation Register Effect "1, " ← line 3 dd on line 3 "-" ← “barˮ p Lost Yank - Normal Edition 17
  16. © 2025 Third Intelligence “0 still holds line 1 —

    but p refers to “1 😢 Step 1 yy (copy line 1 "0, “ ← line 1 2 3 p 5 :reg Operation Register Effect v$ line 2 Replaces line 2 with line 1ʼs content “ You didnʼt lose your yank. You just buried it under another register. Lost Yank - Visual Edition 4 DIFFERENT RESULT Pastes “1 instead of “0) p 18
  17. © 2025 Third Intelligence 1. Understanding Register Internals 2. Why

    Numbered Registers Fail You 3. Building a Safer, Intentional Editing Workflow 4. Beyond Basics: Expressions, Macros, and Tricks 5. Clipboard Deep Dive 6. From Understanding to Internalization Agenda 19
  18. © 2025 Third Intelligence ✔ Prevent accidental overwrites ✔ Preserve

    important registers (esp. ") ✔ Control what goes where ✔ Know when to use blackhole ("_) Editing Without Accidents 20
  19. © 2025 Third Intelligence - "0 always holds the last

    yank, not delete/change. - So even if you delete something, your last yy or yw is still safe. - After an accidental delete, use "0p to recover it. - P variants work too — "0P, "+P+, etc. Using "0 Intentionally Command “0p Paste the last yanked text, even after deletes “0P Same, but paste before the cursor Meaning 21
  20. © 2025 Third Intelligence Blackhole Register — The Unsung Hero

    How it works Like /dev/null - text sent here are discarded Affected Scope Does NOT affect any other registers Use when you… Want to delete without overwriting your yank nnoremap D "_D Set with: 22
  21. © 2025 Third Intelligence ✅ Solved Use blackhole register for

    destructive ops By default, every delete / change updates - the unnamed register (“) - the numbered registers (ˮ19), pushing previous deletes down the stack. → A simple x can destroy text available for p. Prevent small deletes from polluting “- and “19 Stop Losing Your Yanks on Delete ❌ Problem x, d, c overwrites important registers! nnoremap x "_x nnoremap X "_X nnoremap d "_d " add more as needed, e.g. nnoremap C "_C 23
  22. © 2025 Third Intelligence - Visual p replace selection. This

    operation acts as a delete followed by a paste. - The deleted selection overwrites the unnamed register (“) and the numbered registers (“1-9). → Your previous yank is gone. Visual Replace without Overwriting " ✅ Resolved ❌ Problem vnoremap p "_dP vnoremap P "_dp _dp: delete to “_ (no register), then paste. → Preserves your previous yank 24
  23. © 2025 Third Intelligence You can store text manually in

    named registers "a-z Perfect for persistent yanks or working sets. Keep multiple “Safe buffersˮ for different contexts → Does NOT interfere with “0 (last yank) or the system clipboard. Named Registers as Safe Zones "ayiw " yank word into register a "bp " paste from register b 25
  24. © 2025 Third Intelligence 1. Understanding Register Internals 2. Why

    Numbered Registers Fail You 3. Building a Safer, Intentional Editing Workflow 4. Beyond Basics: Expressions, Macros, and Tricks 5. Clipboard Deep Dive 6. From Understanding to Internalization Agenda 26
  25. © 2025 Third Intelligence Key Insert Mode C-r> Basics Evaluate

    & insert result <C-r>0 “0  Last Yank Insert last yanked text <C-r>” Unnamed Register <C-r>+ / <C-r>* System Clipboard Paste from OS clipboard <C-r>. Last Inserted Text Reuse last inserted string <C-r>= Expression Register Source Register Typical Use <C-r>/ Last Search Pattern Insert previous search keyword <C-r>: Last Ex Command Insert last executed command Insert most recent text operation Insert previous file path <C-r>@ Last Macro Register Insert literal macro content <C-r>% Current File Path Insert current filepath <C-r># Alternate File Path <C-r>=setreg() Any Custom Register Dynamic template or variable insert Everything Vim remembers — yanks, deletes, searches, commands, macros — can be inserted directly. Think of C-r> as:  “Read anything Vim knows — right where youʼre typing.ˮ 27
  26. © 2025 Third Intelligence Expand registers or last command inline.

    Abbreviations for Quick Access iabbrev @@ <C-r>@ " last macro text iabbrev !! <C-r>: " last Ex command iabbrev ?? <C-r>/ " last search pattern iabbrev ** <C-r>=strftime("%Y-%m-%d")<CR> " current date autocmd FileType markdown inoreabbrev <buffer> ;dt <C-r>=strftime("%Y-%m-%d")<CR> 28
  27. © 2025 Third Intelligence Dynamic Templates with C-r>= Insert dynamic

    content: date, filename, clipboard… inoremap <C-x>d <C-r>=strftime("%Y-%m-%d")<CR> " insert current date inoremap <C-x>f <C-r>=expand("%:t")<CR> " insert current filename inoremap <C-x>p <C-r>=system('pbpaste')<CR> " insert clipboard content 29
  28. © 2025 Third Intelligence Function-based Templates augroup GitCommit autocmd! autocmd

    FileType gitcommit iabbrev <buffer> #fix <C-r>=GitCommitTemplate('fix')<CR> augroup END function! GitCommitTemplate(type) abort " Only expand at the first (empty) line if line('.') != 1 || getline(1) !~ '^\s*$' return '#'.a:type endif let l:root = systemlist('git rev-parse --show-toplevel')[0] " TODO: add error handling let l:repo = fnamemodify(l:root, ':t') let l:file = expand('%:p') let l:scope = '' if l:repo ==# 'vim' " TODO: set scope endif let l:branch = systemlist('git rev-parse --abbrev-ref HEAD')[0] let l:ticket = matchstr(l:branch, '\v([A-Z]+-\d+)') let l:ticket_part = empty(l:ticket) ? '' : (l:ticket . ' ') return printf('%s(%s): %s', a:type, l:scope, l:ticket_part) endfunction 👉 Generates commit message prefix like fix(main): ABC123 based on current file and branch 30
  29. © 2025 Third Intelligence ✔ Smarter than abbreviations ✔ Lighter

    than snippet plugins ✔ More context-aware than macros ✔ Powered by the full flexibility of Vim script Function-based Templates 31
  30. © 2025 Third Intelligence Literal Search via Registers :%s/\V<C-r>0/<C-r>=escape(@0, '\\')<CR>/g

    - \V → disables regex magic (treats everything as literal) - <C-r>0 → inserts the last yanked text - <C-r>=escape(@0, '\\')<CR> → dynamically escapes regex meta characters This lets you safely search or replace the exact text you copied, even if it contains regex characters like *, . or \ 32
  31. © 2025 Third Intelligence [DEBUG] starting [INFO] initializing [ERROR] failed

    Substitute with Expressions :%s/{pattern}/\=@a/g :%s/{pattern}/\=EXPRESSION/g :%s/\v\[(\a+)\]/\='[' . toupper(submatch(1)) . ']'/g 👉 Use \= in RHS to evaluate expressions. Pattern Tips: <C-r>0 → last yank / <C-r><C-w> → word under cursor [debug] starting [Info] initializing [ERROR] failed AFTER BEFORE 33
  32. © 2025 Third Intelligence Apply macro a on every line

    that matches the pattern Programmatic Macros :let @q = "AyyjP" @q @="AyyjP"<CR> xnoremap Q :normal! @q<CR> :g/{pattern}/         normal! @a Generate and run macros without recording Apply macro q to every line in the current Visual selection 34
  33. © 2025 Third Intelligence 👉 Capture command outputs into registers

    :redir and :put :redir @a | registers | redir END :put a :put =execute('messages') 35
  34. © 2025 Third Intelligence {type?}: - c - characterwise (default)

    - l - linewise - b - blockwise - n - normal-mode keys (macro) 👈 setreg() — Scriptable Editing Pipelines call setreg({reg}, {text}, {type?}) An API to edit what @a uses under the hood let @q = 'I// <Esc>j' call setreg('q', 'I// <Esc>j', 'n') :'<,'>normal @q Equivalent to: But setreg() allows type control (n, blockwise, etc.) — more powerful for programmatic use. 36
  35. © 2025 Third Intelligence Injecting Macros with setreg() Clear and

    script-friendly Feature Syntax style Simple and concise Explicit function call Type specification Not possible (always characterwise) Macro injection Possible but treated as a string n treats it explicitly as key sequence Multi-line List A bit awkward Natural with [line1, line2] Readability / Extensibility Short and quick let @q = … setreg(‘q’, …, ‘n’) Can specify n, b, etc. for type 37
  36. © 2025 Third Intelligence :redir → register → { :put

    | @ | <C-r> | +clipboard } Why Use Registers in the Middle? redir => result silent! ls redir END call setreg('r', result) :put r " paste into buffer <C-r>r " insert in Insert mode @r " run as macro (if keys) call setreg('+', result) " send to clipboard Reuse anywhere: setreg() = a practical bridge between commands, macros, and clipboard. Use it once — reuse it anywhere. 38
  37. © 2025 Third Intelligence 1. Understanding Register Internals 2. Why

    Numbered Registers Fail You 3. Building a Safer, Intentional Editing Workflow 4. Beyond Basics: Expressions, Macros, and Tricks 5. Clipboard Deep Dive 6. From Understanding to Internalization Agenda 39
  38. © 2025 Third Intelligence 1. Understanding Register Internals 2. Why

    Numbered Registers Fail You 3. Building a Safer, Intentional Editing Workflow 4. Beyond Basics: Expressions, Macros, and Tricks 5. Clipboard Deep Dive 6. From Understanding to Internalization Agenda 5A. Clipboard & Register foundations 5B. Clipboard Usage Philosophies & Strategies 5C. Changes in Vim9 40
  39. © 2025 Third Intelligence Registers vs Clipboards Register “0 Only

    on yank ❌ None (internal only) “(unnamed) “+ Explicit ops / unnamedplus Updated on OS Link Yank / Delete / Change System Clipboard Theyʼre not the same. “* Explicit ops / unnamed Redirected to "+ / ”* depending on clipboard Primary Selection X11 41
  40. © 2025 Third Intelligence - "0 = internal only -

    "+ → System Clipboard via "+y - "* → Primary Selection via "*y Vim → OS(No clipboard settings) 👉So when you just run yy, it updates only "0 and ", not the system clipboards. 42
  41. © 2025 Third Intelligence OS  Vim Direction Vim →

    OS "+y, set clipboard=unnamedplus OS  Vim OS  Vim (auto) unnamedplus How Description "+p / <C-r>+ OS clipboard → "+ → " → p Paste from OS clipboard into Vim Copy from Vim to OS clipboard 44
  42. © 2025 Third Intelligence 1. Understanding Register Internals 2. Why

    Numbered Registers Fail You 3. Building a Safer, Intentional Editing Workflow 4. Beyond Basics: Expressions, Macros, and Tricks 5. Clipboard Deep Dive 6. From Understanding to Internalization Agenda 5A. Clipboard & Register foundations 5B. Clipboard Usage Philosophies & Strategies 5C. Changes in Vim9 46
  43. © 2025 Third Intelligence Two Clipboard Philosophies Approach Always Sync

    set clipboard=unnamedplus Automatically syncs all yanks and pastes with the system clipboard. Explicit Control Description Pros Use "+ or "* manually to control when Vim interacts with the system clipboard. Cons Redirected to "+ if unnamedplus Seamless and intuitive experience. Predictable and script-friendly. Risk of accidental overwrites. 47
  44. © 2025 Third Intelligence ✔ Map common "+ operations to

     easier keys ✔ Keep "0" clean during Visual  pastes ✔ Combine explicit control with  daily convenience Mapping & Hybrid Approaches " Frequently used nnoremap <Space>p "+p vnoremap <Space>p "+p " Safe paste in visual mode vnoremap p "_dP vnoremap P "_dp " Use system clipboard only when intended nnoremap <leader>p "+p xnoremap <leader>y "+y nnoremap <leader>y "+y 48
  45. © 2025 Third Intelligence Controlled Sync with TextYankPost ✔ Auto-sync

    every yank to "+  — even without unnamedplus. ✔ Keeps explicit control for   deletes and changes. ✔ Can add filetype-specific   conditions if needed. augroup YankToClipboard autocmd! autocmd TextYankPost * \ if v:event.operator is 'y' | \ call setreg('+', getreg('0')) | \ endif augroup END 49
  46. © 2025 Third Intelligence 1. Understanding Register Internals 2. Why

    Numbered Registers Fail You 3. Building a Safer, Intentional Editing Workflow 4. Beyond Basics: Expressions, Macros, and Tricks 5. Clipboard Deep Dive 6. From Understanding to Internalization Agenda 5A. Clipboard & Register foundations 5B. Clipboard Usage Philosophies & Strategies 5C. Changes in Vim9 50
  47. © 2025 Third Intelligence - Up to Vim 9.0 -

    Vim with the +clipboard feature could access both "+ and "* directly. - Worked automatically on X11 or GUI builds. - Since Vim 9.1.x? - Clipboard support was split into modular features: - +xterm_clipboard → handles "+ System clipboard on X11 - +wayland_clipboard → handles "+ System clipboard on Wayland) - +clipboard_provider → enables custom backends via v:clipproviders - The old +clipboard flag was split for modularity. - If neither X11 nor Wayland clipboard is compiled: - "+ becomes unavailable. - "* still works in most environments — PRIMARY selection on X11, and behaves like "+ on macOS/Windows. From +clipboard to modular clipboards 51
  48. © 2025 Third Intelligence From +clipboard to modular clipboards “*

    register Primary selection, X11 only) - Independent from build options - Still available in most X11 and macOS/Windows builds 52
  49. © 2025 Third Intelligence - v:clipproviders : A dictionary defining

    how to handle “+ and “*. - clipmethod : Determines which clipboard providers to use and in what order. Vim 9.1.x clipboard settings v:clipproviders.pb = { available: function('PB_Available'), paste: { '+': function('PB_Paste'), '*': function('PB_Paste') }, copy: { '+': function('PB_Copy'), '*': function('PB_Copy') }, } " Make pb the preferred clipboard provider. set clipmethod=pb,gui,x11,wayland endif " Register '*' and '+' for all yank, delete, change, and put operations. " unnamedplus is available when +xterm_clipboard / +wayland_clipboard / gui_running set clipboard=unnamed,unnamedplus 53
  50. © 2025 Third Intelligence 1. Understanding Register Internals 2. Why

    Numbered Registers Fail You 3. Building a Safer, Intentional Editing Workflow 4. Beyond Basics: Expressions, Macros, and Tricks 5. Clipboard Deep Dive 6. From Understanding to Internalization Agenda 54
  51. © 2025 Third Intelligence 🚀 Our Next Steps… - Revisit

    :reg regularly — observe, reflect, refine - Start with one mapping or habit at a time - Explore <C-r>=, setreg(), and macros in your own workflow - Let registers flow through your editing, not around it Understanding → Mastery → Internalization Understanding Mastery Internalization Know how registers work "0, ", "*, "*, yank flows Use them intentionally "_d, mappings, <C-r>, setreg() No hesitation, fluid editing 55