/* Copyright 2026 Marimo. All rights reserved. */ import { langs } from "@uiw/codemirror-extensions-langs"; import ReactCodeMirror, { EditorView, keymap, Prec, type ReactCodeMirrorRef, } from "@uiw/react-codemirror"; import { HelpCircleIcon, LayersIcon, PlayIcon, SkipForwardIcon, TrashIcon, } from "lucide-react"; import React, { memo } from "react"; import { cn } from "@/utils/cn"; import { Button } from "../ui/button"; import { Tooltip } from "../ui/tooltip"; import "./debugger-code.css"; import { useKeydownOnElement } from "@/hooks/useHotkey"; import { useInputHistory } from "@/hooks/useInputHistory"; interface Props { code: string; onSubmit: (code: string) => void; } export const Debugger: React.FC = ({ code, onSubmit }) => { return (
); }; const DebuggerOutput: React.FC<{ code: string; }> = memo((props) => { const ref = React.useRef({}); return ( .cm-editor]:pr-0 overflow-hidden dark"} readOnly={true} editable={false} basicSetup={{ lineNumbers: false, }} extensions={[ langs.sh(), EditorView.updateListener.of((update) => { if (update.docChanged) { ref.current.view?.dispatch({ selection: { anchor: update.state.doc.length, head: update.state.doc.length, }, scrollIntoView: true, }); } }), ]} /> ); }); DebuggerOutput.displayName = "DebuggerOutput"; const DebuggerInput: React.FC<{ onSubmit: (code: string) => void; }> = ({ onSubmit }) => { const [value, setValue] = React.useState(""); const ref = React.useRef(null); const { navigateUp, navigateDown, addToHistory } = useInputHistory({ value, setValue, }); // Capture some events for command history navigation useKeydownOnElement(ref, { ArrowUp: navigateUp, ArrowDown: navigateDown, }); return (
.cm-editor]:pr-0 overflow-hidden dark border-t-4" } value={value} autoFocus={true} basicSetup={{ lineNumbers: false, }} extensions={[ langs.py(), Prec.highest( keymap.of([ { key: "Enter", preventDefault: true, stopPropagation: true, run: () => { const v = value.trim().replaceAll("\n", "\\n"); if (!v) { return true; } addToHistory(v); onSubmit(v); setValue(""); return true; }, }, { key: "Shift-Enter", preventDefault: true, stopPropagation: true, run: (view: EditorView) => { // Insert newline and move cursor to end of line view.dispatch({ changes: { from: view.state.selection.main.to, insert: "\n", }, }); return true; }, }, ]), ), ]} onChange={(value) => setValue(value)} />
); }; export const DebuggerControls: React.FC<{ onSubmit: (code: string) => void; onClear?: () => void; }> = ({ onSubmit, onClear }) => { const buttonClasses = cn( "m-0 w-9 h-8 bg-(--slate-2) text-(--slate-11) hover:text-(--blue-11) rounded-none hover:bg-(--sky-3) hover:border-(--blue-8)", "first:rounded-l-lg first:border-l border-t border-b hover:border", "last:rounded-r-lg last:border-r", ); const iconClasses = "w-5 h-5"; return (
{onClear && ( )}
); };