# gnome_to_kitty.py
import subprocess
import re
import ast
import sys
def get_profile_uuid():
try:
cmd = ["gsettings", "get", "org.gnome.Terminal.ProfilesList", "default"]
result = subprocess.check_output(cmd).decode("utf-8").strip()
return result.strip("'")
except subprocess.CalledProcessError:
print("# Error: Failed to get GNOME Terminal Profile UUID", file=sys.stderr)
sys.exit(1)
def get_setting(uuid, key):
"""Read keys from org.gnome.Terminal.Legacy.Profile"""
schema = "org.gnome.Terminal.Legacy.Profile"
path = f"/org/gnome/terminal/legacy/profiles:/:{uuid}/"
cmd = ["gsettings", "get", f"{schema}:{path}", key]
try:
result = subprocess.check_output(cmd).decode("utf-8").strip()
if result.startswith("'") and result.endswith("'"):
return result[1:-1]
return result
except subprocess.CalledProcessError:
return None
def clean_color(color_str):
"""
1. rgb(r, g, b) -> #RRGGBB
2. #RRRRGGGGBBBB (16-bit) -> #RRGGBB
3. #RRGGBB -> #RRGGBB
"""
if not color_str:
return None
# rgb(28,28,28)
rgb_match = re.match(r"rgb\(\s*(\d+),\s*(\d+),\s*(\d+)\)", color_str)
if rgb_match:
r, g, b = map(int, rgb_match.groups())
return f"#{r:02x}{g:02x}{b:02x}"
# 16-bit Hex: #RRRRGGGGBBBB
# High Byte is all we need
if color_str.startswith("#") and len(color_str) == 13:
# Index: 0 1234 5678 9012
# Value: # RRRR GGGG BBBB
return f"#{color_str[1:3]}{color_str[5:7]}{color_str[9:11]}"
return color_str
def parse_font(font_str):
if not font_str:
return "Monospace", 11.0
match = re.match(r"^(.*)\s+(\d+(\.\d+)?)$", font_str)
if match:
return match.group(1), match.group(2)
return font_str, 11.0
def map_cursor_shape(shape):
mapping = {'block': 'block', 'ibeam': 'beam', 'underline': 'underline'}
return mapping.get(shape, 'block')
def main():
uuid = get_profile_uuid()
print(f"# Generated from GNOME Terminal Profile: {uuid}")
print("# Copy content below to your ~/.config/kitty/kitty.conf\n")
# Fonts
font_entry = get_setting(uuid, "font")
use_system_font = get_setting(uuid, "use-system-font")
if use_system_font == 'true':
try:
sys_font_cmd = ["gsettings", "get", "org.gnome.desktop.interface", "monospace-font-name"]
font_entry = subprocess.check_output(sys_font_cmd).decode("utf-8").strip().strip("'")
except:
font_entry = "Monospace 12"
family, size = parse_font(font_entry)
print(f"## Fonts")
print(f"font_family {family}")
print(f"font_size {size}")
print("")
# Colors
print(f"## Color Scheme")
fg = clean_color(get_setting(uuid, "foreground-color"))
bg = clean_color(get_setting(uuid, "background-color"))
palette_str = get_setting(uuid, "palette")
if fg: print(f"foreground {fg}")
if bg: print(f"background {bg}")
if palette_str:
try:
palette = ast.literal_eval(palette_str)
print("\n# ANSI Colors (0-15)")
for i, raw_color in enumerate(palette):
if i < 16:
hex_color = clean_color(raw_color)
print(f"color{i:<2} {hex_color}")
except:
print("# Warning: Failed to parse palette string")
# Cursor
print(f"\n## Cursor")
cursor_shape = get_setting(uuid, "cursor-shape")
print(f"cursor_shape {map_cursor_shape(cursor_shape)}")
cursor_blink = get_setting(uuid, "cursor-blink-mode")
if cursor_blink == 'off':
print("cursor_blink_interval 0")
else:
print("cursor_blink_interval -1")
# Behavior
print(f"\n## Behavior")
scrollback = get_setting(uuid, "scrollback-lines")
if scrollback:
print(f"scrollback_lines {scrollback}")
bell = get_setting(uuid, "audible-bell")
if bell == 'true':
print("enable_audio_bell yes")
else:
print("enable_audio_bell no")
print("window_padding_width 4")
if __name__ == "__main__":
main()