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
Tweet

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