pmacs context menu: clipboard commands/keys + LSP context accessor (Q#CM5/Q#CM6)

The Lua glue that gives the menu real items to surface.

- `edit.copy/cut/paste/select-all` commands (Q#CM6) over the core
  clipboard, with the Emacs kill/yank bindings `M-w`/`C-w`/`C-y` and
  `C-x h` (the CUA trio's keys are already bound: `C-a` line-start,
  `C-v` page-down).
- `pmacs.lsp.active_attachment()` (Q#CM5): a pure, side-effect-free
  attachment lookup for the menu's `symbol`/`diagnostic` visibility
  checks. Unlike `attached_for_active`, it never triggers an attach just
  because the menu opened.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014TXbAwk27agwhrNNrhLi2U
This commit is contained in:
Levi Neuwirth 2026-06-27 22:03:58 -04:00
parent 8929bf0d25
commit b934723dfd
3 changed files with 46 additions and 0 deletions

View File

@ -160,6 +160,31 @@ cmd { name = "region.cancel",
description = "Drop any active selection without changing the cursor.",
fn = function() ed.clear_selection() end }
-- Clipboard (Q#CM6) ----------------------------------------------------------
-- Copy/cut publish the selection to the OS clipboard (OSC 52 in the TUI,
-- arboard in the GPU); paste inserts the in-app slot, which Ctrl-V /
-- bracketed paste also refreshes. The default bindings are the Emacs
-- kill/yank set (M-w / C-w / C-y, C-x h), which were all free.
cmd { name = "edit.copy",
description = "Copy the active region to the clipboard.",
fn = function()
if not ed.clipboard_copy() then ed.set_status("no region") end
end }
cmd { name = "edit.cut",
description = "Cut the active region to the clipboard.",
fn = function()
if not ed.clipboard_cut() then ed.set_status("no region") end
end }
cmd { name = "edit.paste",
description = "Paste the clipboard at the cursor, replacing any region.",
fn = function()
if not ed.clipboard_paste() then ed.set_status("clipboard empty") end
end }
cmd { name = "edit.select-all",
description = "Select the whole buffer.",
fn = function() ed.select_all() end }
-- File I/O -------------------------------------------------------------------
cmd { name = "buffer.save", description = "Save the current buffer to its backing file.",

View File

@ -103,6 +103,15 @@ bind("C-S-<right>", "cursor.select-word-right")
bind("C-S-<up>", "cursor.select-paragraph-up")
bind("C-S-<down>", "cursor.select-paragraph-down")
-- Clipboard (Q#CM6). The Emacs kill/yank set --- all of these were free
-- in the default map (C-a / C-v are taken for line-start / page-down, so
-- the CUA trio would have clobbered motion). C-w cuts, M-w copies, C-y
-- pastes; C-x h selects the whole buffer (Emacs mark-whole-buffer).
bind("M-w", "edit.copy")
bind("C-w", "edit.cut")
bind("C-y", "edit.paste")
bind("C-x h", "edit.select-all")
-- Undo / redo ----------------------------------------------------------------
--
-- Multiple undo bindings exist because terminals translate Ctrl+/

View File

@ -532,6 +532,18 @@ local function attached_for_active()
return attach_buffer(buf)
end
-- Pure, side-effect-free attachment lookup for the active buffer:
-- returns the live record (with `.uri`) when a server is already
-- attached, else nil. Unlike `attached_for_active`, it never *triggers*
-- an attach --- the context menu (Q#CM3) calls it to decide whether to
-- show symbol/diagnostic items, and must not perturb LSP state just by
-- opening.
function pmacs.lsp.active_attachment()
local buf = pmacs.window.buffer()
if not buf then return nil end
return attachments[tostring(buf)]
end
-- Hooks --------------------------------------------------------------------
pmacs.hook.add("buffer.after-load", function()