marketplace/productivity

Clipboard Slots

Copy the clipboard into one of five numbered slots on demand, then type a slot back out with a chord.

@rebindv0.1.0free

More install options
$rebind install @rebind/clipboard-slots

Gallery

Clipboard Slots preview

Readme

Five numbered slots for text you copied. Capture is explicit, insertion is typed, and the clipboard itself is never replaced.

Use

  1. Copy something as usual.
  2. Hold the capture modifier (default Ctrl+Alt) and press a slot key, 1 to 5. The slot now holds that text.
  3. Later, hold the insert modifier (default Ctrl+Shift) and press the same key. The slot is typed into the focused app once the chord is released.

Both modifiers and every slot key are configurable. Restart the script after changing a key.

What it does not do

  • No clipboard history. Nothing is captured unless you press the capture chord.
  • No persistence. Slots are held in memory and cleared when the script stops.
  • No clipboard writes. Insertion types the text; your clipboard keeps whatever you copied last.

Limits

  • Slot keys are captured system wide while the script runs, for both chords.
  • Text is typed through the operating system. Very long captures take a moment, and some apps drop characters when they arrive faster than expected.

Reviews

No reviews yet. Write a review in the app.

Source

Version 0.1.0 (current)

main.luau

-- Clipboard Slots: capture the clipboard into a numbered slot, type it back
-- later. Slots live in memory only and vanish when the script stops.

local SLOTS = 5

local MOD_NAMES = {
  "Ctrl+Alt",
  "Ctrl+Shift",
  "Alt+Shift",
  "Ctrl+Alt+Shift",
  "Cmd/Win+Alt",
  "Cmd/Win+Shift",
}
local MODS = {
  ["Ctrl+Alt"] = { ctrl = true, alt = true },
  ["Ctrl+Shift"] = { ctrl = true, shift = true },
  ["Alt+Shift"] = { alt = true, shift = true },
  ["Ctrl+Alt+Shift"] = { ctrl = true, alt = true, shift = true },
  ["Cmd/Win+Alt"] = { win = true, alt = true },
  ["Cmd/Win+Shift"] = { win = true, shift = true },
}

local schema = {
  captureModifier = UI.Select(
    "Ctrl+Alt",
    MOD_NAMES,
    { label = "Capture: modifier + slot key", tab = "Settings" }
  ),
  insertModifier = UI.Select(
    "Ctrl+Shift",
    MOD_NAMES,
    { label = "Insert: modifier + slot key", tab = "Settings" }
  ),
}
for n = 1, SLOTS do
  schema[`key{n}`] =
    UI.Keybind(tostring(n), { label = `Slot {n} key`, tab = "Settings" })
end
local cfg = UI.Schema(schema)

local slots = {}

local function chordHeld(name)
  local want = MODS[name] or {}
  local have = Input.GetModifiers()
  for _, m in { "ctrl", "alt", "shift", "win" } do
    if (want[m] == true) ~= have[m] then
      return false
    end
  end
  return true
end

local function capture(n)
  local ok, text = pcall(Clipboard.Get)
  if not ok then
    Log.Error(`slot {n}: {text}`)
    UI.Notify("Clipboard could not be read", "error")
    return
  end
  if text == nil or text == "" then
    UI.Notify("Clipboard has no text", "warning")
    return
  end
  slots[n] = text
  UI.Notify(`Slot {n}: {#text} characters`, "success")
end

-- type only after the chord is fully released: a modifier still held turns
-- the inserted characters into shortcuts in the receiving app.
local function insert(n)
  Run(function()
    local waited = 0
    while waited < 1000 do
      local m = Input.GetModifiers()
      if not (m.ctrl or m.alt or m.shift or m.win) then
        break
      end
      Sleep(10)
      waited += 10
    end
    if waited >= 1000 then
      UI.Notify("Release the modifier keys to insert", "warning")
      return
    end
    local text = slots[n]
    if text == nil then
      UI.Notify(`Slot {n} is empty`, "warning")
      return
    end
    local ok, err = pcall(System.TypeText, text)
    if not ok then
      Log.Error(`slot {n}: {err}`)
      UI.Notify(`Slot {n} could not be typed`, "error")
    end
  end)
end

for n = 1, SLOTS do
  local key = cfg[`key{n}`]
  Bind(key, {
    when = function()
      return chordHeld(cfg.captureModifier)
    end,
    action = function()
      capture(n)
      return nil
    end,
  })
  Bind(key, {
    when = function()
      return chordHeld(cfg.insertModifier)
    end,
    action = function()
      return nil
    end,
    release = function()
      insert(n)
    end,
  })
end

function OnStart()
  Log.Info(
    `{cfg.captureModifier} + key captures, {cfg.insertModifier} + key types. Slots clear on stop.`
  )
end

function OnStop()
  slots = {}
end