Skip to content

Instantly share code, notes, and snippets.

@truebit
Last active March 22, 2024 08:25
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save truebit/d79b8018666d65e95970f208d8f5d149 to your computer and use it in GitHub Desktop.
Save truebit/d79b8018666d65e95970f208d8f5d149 to your computer and use it in GitHub Desktop.
Kitty Terminal: pull down from top like iTerm2
local spaces = require("hs.spaces") -- https://github.com/asmagill/hs._asm.spaces
-- Switch kitty
hs.hotkey.bind({'command'}, 'escape', function () -- change your own hotkey combo here, available keys could be found here:https://www.hammerspoon.org/docs/hs.hotkey.html#bind
local BUNDLE_ID = 'net.kovidgoyal.kitty' -- more accurate to avoid mismatching on browser titles
function getMainWindow(app)
-- get main window from app
local win = nil
while win == nil do
win = app:mainWindow()
end
return win
end
function moveWindow(kitty, space, mainScreen)
-- move to main space
local win = getMainWindow(kitty)
if win:isFullScreen() then
hs.eventtap.keyStroke('fn', 'f', 0, kitty)
end
winFrame = win:frame()
scrFrame = mainScreen:fullFrame()
winFrame.w = scrFrame.w
winFrame.y = scrFrame.y
winFrame.x = scrFrame.x
win:setFrame(winFrame, 0)
spaces.moveWindowToSpace(win, space)
if win:isFullScreen() then
hs.eventtap.keyStroke('fn', 'f', 0, kitty)
end
win:focus()
end
local kitty = hs.application.get(BUNDLE_ID)
if kitty ~= nil and kitty:isFrontmost() then
kitty:hide()
else
local space = spaces.activeSpaceOnScreen()
local mainScreen = hs.screen.mainScreen()
if kitty == nil and hs.application.launchOrFocusByBundleID(BUNDLE_ID) then
local appWatcher = nil
appWatcher = hs.application.watcher.new(function(name, event, app)
if event == hs.application.watcher.launched and app:bundleID() == BUNDLE_ID then
getMainWindow(app):move(hs.geometry({x=0,y=0,w=1,h=0.4})) -- move kitty window on top, you could set the window percentage here
app:hide()
moveWindow(app, space, mainScreen)
appWatcher:stop()
end
end)
appWatcher:start()
end
if kitty ~= nil then
moveWindow(kitty, space, mainScreen)
end
end
end)
# make your kitty window borderless
hide_window_decorations titlebar-and-corners
# make kitty app quit entirely instead of leaving null window, which made the script hard to detect kitty window
macos_quit_when_last_window_closed yes
# this one is optional, would quit kitty tab more quickly
confirm_os_window_close 0
# this one is optional, as hammerspoon script would move window in script line 45
remember_window_size yes
@truebit
Copy link
Author

truebit commented Oct 19, 2023

Tested on HammerSpoon Version 0.9.100(6815) and Kitty Version 0.30.1 with Mac OS X Ventura 13.3.1(a)

  • firstly, configure kitty.conf to
    • hide kitty titlebar and round corners;
    • disable the window close confirmation dialog;
    • enable quit app when no window in kitty; (make hammerspoon more easily to determine kitty app)
  • then replace the init.lua for hammerspoon;

Now you can use command+escape to launch/show and hide kitty, this script supports:

  • multi window and space show/hide;
  • more accurate kitty app detection using bundle id;
  • automatically move kitty window to the top of the screen

@CrazyCatZhang
Copy link

I have a problem, that is, after setting it up, when I wake up Kitty on other screens, it will jump to the home screen. I want it to be able to call up the display on any screen like iTerm2. How to solve this problem?

@truebit
Copy link
Author

truebit commented Jan 22, 2024

I have a problem, that is, after setting it up, when I wake up Kitty on other screens, it will jump to the home screen. I want it to be able to call up the display on any screen like iTerm2. How to solve this problem?

the code already considered that situation. It works on Ventura and Sonoma, which I tested on my own MacBook Pro.

If your environment not support it, you could dig into moveWindow function in the script

@CrazyCatZhang
Copy link

My Mac system is Sonoma~

@CrazyCatZhang
Copy link

Screen.Recording.2024-01-22.at.21.20.59.-.01.mp4

@truebit
Copy link
Author

truebit commented Jan 23, 2024

My solution only supports multi hardware screen switch and display like iTerm2 top-down window.
According to your video, you modified my script to adapt your requirement. If that's not what you intended to, follow this gist carefully, espcially the kitty configuration.

@CrazyCatZhang
Copy link

I just modified the percentage of the screen display and set the height to 1

@truebit
Copy link
Author

truebit commented Jan 23, 2024 via email

@CrazyCatZhang
Copy link

👌🏻, thanks~

@ildar-aim
Copy link

Hello , I am trying to hide kitty on switching to another workspace by CTRL+1/2/3/4 (losing focus)

Do you know probably how to overcome this error (binding to system hotkey )?

2024-03-22 10:01:12: 10:01:12 ERROR:   LuaSkin: hs.hotkey:enable() keycode: 18, mods: 0x1000, RegisterEventHotKey failed: -9878
2024-03-22 10:01:12: 10:01:12 ERROR:   LuaSkin: This hotkey is already registered. It may be a duplicate in your Hammerspoon config, or it may be registered by macOS. See System Preferences->Keyboard->Shortcuts

here is not working code for CTRL+1 hotkey

-- 09:57:05.838  INFO   wezterm_gui::termwindow::keyevent     > key_event KeyEvent { key: Char('1'), modifiers:{CTRL}, leds: (empty), repeat_count: 1, key_is_down: false, raw: Some(RawKeyEvent { key: Char('1'), modifiers: NONE, leds: (empty), phys_code: Some(K1), raw_code: 18, repeat_count: 1, key_is_down: false, handled: Handled(false) }) }
hs.hotkey.bind({"ctrl"}, 18, function () -- change your own hotkey combo here, available keys could be found here:https://www.hammerspoon.org/docs/hs.hotkey.html#bind
  local BUNDLE_ID = 'net.kovidgoyal.kitty' -- more accurate to avoid mismatching on browser titles

  local kitty = hs.application.get(BUNDLE_ID)
  if kitty ~= nil and kitty:isFrontmost() then
    kitty:hide()
  end
end)

@truebit
Copy link
Author

truebit commented Mar 22, 2024

Hello , I am trying to hide kitty on switching to another workspace by CTRL+1/2/3/4 (losing focus)

Do you know probably how to overcome this error (binding to system hotkey )?

2024-03-22 10:01:12: 10:01:12 ERROR:   LuaSkin: hs.hotkey:enable() keycode: 18, mods: 0x1000, RegisterEventHotKey failed: -9878
2024-03-22 10:01:12: 10:01:12 ERROR:   LuaSkin: This hotkey is already registered. It may be a duplicate in your Hammerspoon config, or it may be registered by macOS. See System Preferences->Keyboard->Shortcuts

here is not working code for CTRL+1 hotkey

-- 09:57:05.838  INFO   wezterm_gui::termwindow::keyevent     > key_event KeyEvent { key: Char('1'), modifiers:{CTRL}, leds: (empty), repeat_count: 1, key_is_down: false, raw: Some(RawKeyEvent { key: Char('1'), modifiers: NONE, leds: (empty), phys_code: Some(K1), raw_code: 18, repeat_count: 1, key_is_down: false, handled: Handled(false) }) }
hs.hotkey.bind({"ctrl"}, 18, function () -- change your own hotkey combo here, available keys could be found here:https://www.hammerspoon.org/docs/hs.hotkey.html#bind
  local BUNDLE_ID = 'net.kovidgoyal.kitty' -- more accurate to avoid mismatching on browser titles

  local kitty = hs.application.get(BUNDLE_ID)
  if kitty ~= nil and kitty:isFrontmost() then
    kitty:hide()
  end
end)

The error message already told you: "This hotkey is already registered. It may be a duplicate in your Hammerspoon config, or it may be registered by macOS. See System Preferences->Keyboard->Shortcuts"

@ildar-aim
Copy link

I set CTRL + 1/2/3/4 to switch between spaces intentionally in System Preferences->Keyboard->Shortcuts.
The question is
Is it possible to chain something else via hammerspoon in addition to system action?
Ok I see the question is not related to the gist.

Anyway thank you for your efforts!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment