Skip to content

Commit 24fdf0f

Browse files
author
Your Name
committed
Update terminal setup for TOML errors and TOML writting
1 parent c1f037f commit 24fdf0f

6 files changed

Lines changed: 173 additions & 54 deletions

File tree

cecli/commands/terminal_setup.py

Lines changed: 156 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,28 @@ def _backup_file(cls, file_path, io):
158158
@classmethod
159159
def _update_alacritty(cls, path, io, dry_run=False):
160160
"""Updates Alacritty TOML configuration with shift+enter binding."""
161-
if os.environ.get("TERM") != "alacritty":
162-
return False
161+
import tomlkit
162+
163+
# Create directory if it doesn't exist
164+
path.parent.mkdir(parents=True, exist_ok=True)
163165

164166
if not path.exists():
165-
io.tool_output(f"Skipping Alacritty: File not found at {path}")
166-
return False
167+
if dry_run:
168+
io.tool_output(f"DRY-RUN: Would create Alacritty config at {path}")
169+
io.tool_output(
170+
'DRY-RUN: Would add binding: {"key": "Return", "mods": "Shift", "chars": "\\n"}'
171+
)
172+
return True
173+
else:
174+
io.tool_output(f"Creating Alacritty config at {path}")
175+
# Create minimal Alacritty config with shift+enter binding
176+
data = {
177+
"keyboard": {"bindings": [{"key": "Return", "mods": "Shift", "chars": "\n"}]}
178+
}
179+
with open(path, "w", encoding="utf-8") as f:
180+
tomlkit.dump(data, f)
181+
io.tool_output("Created Alacritty config with shift+enter binding.")
182+
return True
167183

168184
# Define the binding to add
169185
new_binding = {"key": "Return", "mods": "Shift", "chars": "\n"}
@@ -173,7 +189,7 @@ def _update_alacritty(cls, path, io, dry_run=False):
173189
io.tool_output(f"DRY-RUN: Would add binding: {new_binding}")
174190
try:
175191
with open(path, "r", encoding="utf-8") as f:
176-
data = toml.load(f)
192+
data = tomlkit.load(f)
177193

178194
# Check if binding already exists
179195
keyboard_section = data.get("keyboard", {})
@@ -195,7 +211,7 @@ def _update_alacritty(cls, path, io, dry_run=False):
195211
else:
196212
io.tool_output("DRY-RUN: Would update Alacritty config.")
197213
return True
198-
except toml.TomlDecodeError:
214+
except toml.TOMLDecodeError:
199215
io.tool_output("DRY-RUN: Error: Could not parse Alacritty TOML file.")
200216
return False
201217
except Exception as e:
@@ -206,7 +222,7 @@ def _update_alacritty(cls, path, io, dry_run=False):
206222

207223
try:
208224
with open(path, "r", encoding="utf-8") as f:
209-
data = toml.load(f)
225+
data = tomlkit.load(f)
210226

211227
# Ensure keyboard section exists
212228
if "keyboard" not in data:
@@ -237,12 +253,12 @@ def _update_alacritty(cls, path, io, dry_run=False):
237253

238254
# Write back to file
239255
with open(path, "w", encoding="utf-8") as f:
240-
toml.dump(data, f)
256+
tomlkit.dump(data, f)
241257

242258
io.tool_output("Updated Alacritty config.")
243259
return True
244260

245-
except toml.TomlDecodeError:
261+
except toml.TOMLDecodeError:
246262
io.tool_output("Error: Could not parse Alacritty TOML file. Is it valid TOML?")
247263
return False
248264
except Exception as e:
@@ -252,9 +268,21 @@ def _update_alacritty(cls, path, io, dry_run=False):
252268
@classmethod
253269
def _update_kitty(cls, path, io, dry_run=False):
254270
"""Appends the Kitty mapping if not present."""
271+
# Create directory if it doesn't exist
272+
path.parent.mkdir(parents=True, exist_ok=True)
273+
255274
if not path.exists():
256-
io.tool_output(f"Skipping Kitty: File not found at {path}")
257-
return False
275+
if dry_run:
276+
io.tool_output(f"DRY-RUN: Would create Kitty config at {path}")
277+
io.tool_output(f"DRY-RUN: Would add binding:\n{cls.KITTY_BINDING.strip()}")
278+
return True
279+
else:
280+
io.tool_output(f"Creating Kitty config at {path}")
281+
# Create Kitty config with shift+enter binding
282+
with open(path, "w", encoding="utf-8") as f:
283+
f.write(cls.KITTY_BINDING)
284+
io.tool_output("Created Kitty config with shift+enter binding.")
285+
return True
258286

259287
if dry_run:
260288
io.tool_output(f"DRY-RUN: Would check Kitty config at {path}")
@@ -290,9 +318,6 @@ def _update_kitty(cls, path, io, dry_run=False):
290318
@classmethod
291319
def _update_konsole(cls, path, io, dry_run=False):
292320
"""Updates Konsole keytab configuration with shift+enter binding."""
293-
if not os.environ.get("KONSOLE_VERSION"):
294-
return False
295-
296321
default_keytab_path = Path(__file__).parent / "terminal_data" / "linux.keytab"
297322

298323
if not path.exists():
@@ -354,10 +379,30 @@ def _update_konsole(cls, path, io, dry_run=False):
354379
@classmethod
355380
def _update_windows_terminal(cls, path, io, dry_run=False):
356381
"""Parses JSON, adds action to 'actions' list and keybinding to 'keybindings' list."""
357-
if not path or not path.exists():
358-
io.tool_output("Skipping Windows Terminal: File not found.")
382+
if not path:
383+
io.tool_output("Skipping Windows Terminal: No path available.")
359384
return False
360385

386+
# Create directory if it doesn't exist
387+
path.parent.mkdir(parents=True, exist_ok=True)
388+
389+
if not path.exists():
390+
if dry_run:
391+
io.tool_output(f"DRY-RUN: Would create Windows Terminal config at {path}")
392+
io.tool_output(f"DRY-RUN: Would add action: {json.dumps(cls.WT_ACTION, indent=2)}")
393+
io.tool_output(
394+
f"DRY-RUN: Would add keybinding: {json.dumps(cls.WT_KEYBINDING, indent=2)}"
395+
)
396+
return True
397+
else:
398+
io.tool_output(f"Creating Windows Terminal config at {path}")
399+
# Create minimal Windows Terminal config with shift+enter binding
400+
data = {"actions": [cls.WT_ACTION], "keybindings": [cls.WT_KEYBINDING]}
401+
with open(path, "w", encoding="utf-8") as f:
402+
json.dump(data, f, indent=4)
403+
io.tool_output("Created Windows Terminal config with shift+enter binding.")
404+
return True
405+
361406
if dry_run:
362407
io.tool_output(f"DRY-RUN: Would check Windows Terminal config at {path}")
363408
io.tool_output(f"DRY-RUN: Would add action: {json.dumps(cls.WT_ACTION, indent=2)}")
@@ -744,42 +789,118 @@ async def execute(cls, io, coder, args, **kwargs):
744789
paths = cls._get_config_paths()
745790

746791
# Check for dry-run mode
747-
dry_run = args == "dry_run"
792+
dry_run = args == "dry_run" or (hasattr(args, "dry_run") and args.dry_run)
748793
if dry_run:
749794
io.tool_output("DRY-RUN MODE: Showing what would be changed without modifying files\n")
750795

796+
# Explicit yes required should always be true for terminal setup
797+
explicit_yes_required = True
798+
751799
updated = False
752800

753801
if "alacritty" in paths:
754-
if cls._update_alacritty(paths["alacritty"], io, dry_run=dry_run):
755-
updated = True
802+
path = paths["alacritty"]
803+
if path.exists():
804+
question = f"Update Alacritty config at {path} to add shift+enter binding?"
805+
else:
806+
question = f"Create new Alacritty config at {path} with shift+enter binding?"
807+
808+
if dry_run or await coder.io.confirm_ask(
809+
question, default="y", explicit_yes_required=explicit_yes_required
810+
):
811+
if cls._update_alacritty(path, io, dry_run=dry_run):
812+
updated = True
756813

757814
if "kitty" in paths:
758-
if cls._update_kitty(paths["kitty"], io, dry_run=dry_run):
759-
updated = True
815+
path = paths["kitty"]
816+
if path.exists():
817+
question = f"Update Kitty config at {path} to add shift+enter binding?"
818+
else:
819+
question = f"Create new Kitty config at {path} with shift+enter binding?"
820+
821+
if dry_run or await coder.io.confirm_ask(
822+
question, default="y", explicit_yes_required=explicit_yes_required
823+
):
824+
if cls._update_kitty(path, io, dry_run=dry_run):
825+
updated = True
760826

761827
if "konsole" in paths:
762-
if cls._update_konsole(paths["konsole"], io, dry_run=dry_run):
763-
updated = True
828+
path = paths["konsole"]
829+
if path.exists():
830+
question = f"Update Konsole keytab at {path} to add shift+enter binding?"
831+
else:
832+
question = f"Create new Konsole keytab at {path} with shift+enter binding?"
833+
834+
if dry_run or await coder.io.confirm_ask(
835+
question, default="y", explicit_yes_required=explicit_yes_required
836+
):
837+
if cls._update_konsole(path, io, dry_run=dry_run):
838+
updated = True
764839

765840
if "windows_terminal" in paths:
766-
if cls._update_windows_terminal(paths["windows_terminal"], io, dry_run=dry_run):
767-
updated = True
841+
path = paths["windows_terminal"]
842+
if path.exists():
843+
question = f"Update Windows Terminal config at {path} to add shift+enter binding?"
844+
else:
845+
question = f"Create new Windows Terminal config at {path} with shift+enter binding?"
846+
847+
if dry_run or await coder.io.confirm_ask(
848+
question, default="y", explicit_yes_required=explicit_yes_required
849+
):
850+
if cls._update_windows_terminal(path, io, dry_run=dry_run):
851+
updated = True
768852

769853
if "vscode" in paths:
770-
if cls._update_vscode(paths["vscode"], io, dry_run=dry_run):
771-
updated = True
772-
# Also update VS Code settings.json for proper shift+enter support
773-
if cls._update_vscode_settings(paths["vscode"], io, dry_run=dry_run):
774-
updated = True
854+
path = paths["vscode"]
855+
if path.exists():
856+
question = f"Update VS Code keybindings at {path} to add shift+enter binding?"
857+
else:
858+
question = f"Create new VS Code keybindings at {path} with shift+enter binding?"
859+
860+
if dry_run or await coder.io.confirm_ask(
861+
question, default="y", explicit_yes_required=explicit_yes_required
862+
):
863+
if cls._update_vscode(path, io, dry_run=dry_run):
864+
updated = True
865+
# Also update VS Code settings.json for proper shift+enter support
866+
settings_question = (
867+
f"Update VS Code settings at {path.parent}/settings.json for proper shift+enter"
868+
" support?"
869+
)
870+
if dry_run or await coder.io.confirm_ask(
871+
settings_question, default="y", explicit_yes_required=explicit_yes_required
872+
):
873+
if cls._update_vscode_settings(path, io, dry_run=dry_run):
874+
updated = True
775875

776876
if "vscode_windows" in paths:
877+
path = paths["vscode_windows"]
777878
io.tool_output("Found Windows host VS Code configuration (running in WSL)")
778-
if cls._update_vscode(paths["vscode_windows"], io, dry_run=dry_run):
779-
updated = True
780-
# Also update Windows host VS Code settings.json
781-
if cls._update_vscode_settings(paths["vscode_windows"], io, dry_run=dry_run):
782-
updated = True
879+
if path.exists():
880+
question = (
881+
f"Update Windows host VS Code keybindings at {path} to add shift+enter binding?"
882+
)
883+
else:
884+
question = (
885+
f"Create new Windows host VS Code keybindings at {path} with shift+enter"
886+
" binding?"
887+
)
888+
889+
if dry_run or await coder.io.confirm_ask(
890+
question, default="y", explicit_yes_required=explicit_yes_required
891+
):
892+
if cls._update_vscode(path, io, dry_run=dry_run):
893+
updated = True
894+
# Also update Windows host VS Code settings.json
895+
settings_question = (
896+
f"Update Windows host VS Code settings at {path.parent}/settings.json for"
897+
" proper shift+enter support?"
898+
)
899+
if dry_run or await coder.io.confirm_ask(
900+
settings_question, default="y", explicit_yes_required=explicit_yes_required
901+
):
902+
if cls._update_vscode_settings(path, io, dry_run=dry_run):
903+
updated = True
783904

784905
if dry_run:
785906
if updated:

requirements.txt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ grep-ast==0.9.0
113113
# via
114114
# -c requirements/common-constraints.txt
115115
# -r requirements/requirements.in
116-
grpcio==1.67.1
116+
grpcio==1.78.0
117117
# via
118118
# -c requirements/common-constraints.txt
119119
# litellm
@@ -421,6 +421,10 @@ tokenizers==0.22.1
421421
# via
422422
# -c requirements/common-constraints.txt
423423
# litellm
424+
tomlkit==0.14.0
425+
# via
426+
# -c requirements/common-constraints.txt
427+
# -r requirements/requirements.in
424428
tqdm==4.67.1
425429
# via
426430
# -c requirements/common-constraints.txt
@@ -453,16 +457,13 @@ truststore==0.10.4
453457
typing-extensions==4.15.0
454458
# via
455459
# -c requirements/common-constraints.txt
456-
# aiosignal
457-
# anyio
458460
# beautifulsoup4
461+
# grpcio
459462
# huggingface-hub
460463
# mcp
461464
# openai
462465
# pydantic
463466
# pydantic-core
464-
# referencing
465-
# starlette
466467
# textual
467468
# typing-inspection
468469
typing-inspection==0.4.2

requirements/common-constraints.txt

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,12 @@ grep-ast==0.9.0
144144
# via -r requirements/requirements.in
145145
griffe==1.15.0
146146
# via banks
147-
grpcio==1.67.1
147+
grpcio==1.78.0
148148
# via
149149
# google-api-core
150150
# grpcio-status
151151
# litellm
152-
grpcio-status==1.67.1
152+
grpcio-status==1.78.0
153153
# via google-api-core
154154
h11==0.16.0
155155
# via
@@ -369,7 +369,7 @@ propcache==0.4.1
369369
# yarl
370370
proto-plus==1.26.1
371371
# via google-api-core
372-
protobuf==5.29.5
372+
protobuf==6.33.5
373373
# via
374374
# google-api-core
375375
# googleapis-common-protos
@@ -548,6 +548,8 @@ tokenizers==0.22.1
548548
# via
549549
# litellm
550550
# transformers
551+
tomlkit==0.14.0
552+
# via -r requirements/requirements.in
551553
torch==2.9.1
552554
# via sentence-transformers
553555
tqdm==4.67.1
@@ -580,10 +582,9 @@ typer==0.20.0
580582
# via -r requirements/requirements-dev.in
581583
typing-extensions==4.15.0
582584
# via
583-
# aiosignal
584585
# aiosqlite
585-
# anyio
586586
# beautifulsoup4
587+
# grpcio
587588
# huggingface-hub
588589
# llama-index-core
589590
# llama-index-workflows
@@ -592,11 +593,8 @@ typing-extensions==4.15.0
592593
# pydantic
593594
# pydantic-core
594595
# pyee
595-
# pytest-asyncio
596-
# referencing
597596
# sentence-transformers
598597
# sqlalchemy
599-
# starlette
600598
# textual
601599
# torch
602600
# typer

0 commit comments

Comments
 (0)