diff --git a/frontend/app/onboarding/onboarding-command.tsx b/frontend/app/onboarding/onboarding-command.tsx
index 783f544e51..d98065dbf6 100644
--- a/frontend/app/onboarding/onboarding-command.tsx
+++ b/frontend/app/onboarding/onboarding-command.tsx
@@ -1,7 +1,7 @@
// Copyright 2025, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
-import { useCallback, useLayoutEffect, useState } from "react";
+import { useCallback, useLayoutEffect, useRef, useState } from "react";
import { FakeBlock } from "./onboarding-layout";
import waveLogo from "/logos/wave-logo.png";
@@ -114,6 +114,7 @@ export const ViewLogoCommand = ({ onComplete }: { onComplete?: () => void }) =>
};
export const EditBashrcCommand = ({ onComplete }: { onComplete?: () => void }) => {
+ const fileNameRef = useRef(`${crypto.randomUUID()}/.bashrc`);
const bashrcContent = `# Aliases
alias ll="ls -lah"
alias gst="git status"
@@ -127,7 +128,13 @@ export PATH="$HOME/.local/bin:$PATH"`;
return (
-
+
);
};
diff --git a/frontend/app/onboarding/onboarding-layout.tsx b/frontend/app/onboarding/onboarding-layout.tsx
index 057aef0fc2..bbe2aece5f 100644
--- a/frontend/app/onboarding/onboarding-layout.tsx
+++ b/frontend/app/onboarding/onboarding-layout.tsx
@@ -15,9 +15,21 @@ export type FakeBlockProps = {
markdown?: string;
imgsrc?: string;
editorText?: string;
+ editorFileName?: string;
+ editorLanguage?: string;
};
-export const FakeBlock = ({ icon, name, highlighted, className, markdown, imgsrc, editorText }: FakeBlockProps) => {
+export const FakeBlock = ({
+ icon,
+ name,
+ highlighted,
+ className,
+ markdown,
+ imgsrc,
+ editorText,
+ editorFileName,
+ editorLanguage,
+}: FakeBlockProps) => {
return (
{editorText ? (
-
+
) : imgsrc ? (

diff --git a/frontend/app/view/codeeditor/codeeditor.tsx b/frontend/app/view/codeeditor/codeeditor.tsx
index 3f278a6825..13c810d6a0 100644
--- a/frontend/app/view/codeeditor/codeeditor.tsx
+++ b/frontend/app/view/codeeditor/codeeditor.tsx
@@ -108,11 +108,12 @@ interface CodeEditorProps {
text: string;
readonly: boolean;
language?: string;
+ fileName?: string;
onChange?: (text: string) => void;
onMount?: (monacoPtr: MonacoTypes.editor.IStandaloneCodeEditor, monaco: Monaco) => () => void;
}
-export function CodeEditor({ blockId, text, language, readonly, onChange, onMount }: CodeEditorProps) {
+export function CodeEditor({ blockId, text, language, fileName, readonly, onChange, onMount }: CodeEditorProps) {
const divRef = useRef
(null);
const unmountRef = useRef<() => void>(null);
const minimapEnabled = useOverrideConfigAtom(blockId, "editor:minimapenabled") ?? false;
@@ -120,7 +121,14 @@ export function CodeEditor({ blockId, text, language, readonly, onChange, onMoun
const wordWrap = useOverrideConfigAtom(blockId, "editor:wordwrap") ?? false;
const fontSize = boundNumber(useOverrideConfigAtom(blockId, "editor:fontsize"), 6, 64);
const theme = "wave-theme-dark";
- const editorPath = useRef(crypto.randomUUID()).current;
+ const uuidRef = useRef(crypto.randomUUID()).current;
+ let editorPath: string;
+ if (fileName) {
+ const separator = fileName.startsWith("/") ? "" : "/";
+ editorPath = blockId + separator + fileName;
+ } else {
+ editorPath = uuidRef;
+ }
React.useEffect(() => {
return () => {
diff --git a/frontend/app/view/preview/preview-edit.tsx b/frontend/app/view/preview/preview-edit.tsx
index f249f7ee7f..a7ec656cc2 100644
--- a/frontend/app/view/preview/preview-edit.tsx
+++ b/frontend/app/view/preview/preview-edit.tsx
@@ -12,10 +12,35 @@ import type * as MonacoTypes from "monaco-editor/esm/vs/editor/editor.api";
import { useEffect } from "react";
import type { SpecializedViewProps } from "./preview";
+export const shellFileMap: Record = {
+ ".bashrc": "shell",
+ ".bash_profile": "shell",
+ ".bash_login": "shell",
+ ".bash_logout": "shell",
+ ".profile": "shell",
+ ".zshrc": "shell",
+ ".zprofile": "shell",
+ ".zlogin": "shell",
+ ".zlogout": "shell",
+ ".kshrc": "shell",
+ ".cshrc": "shell",
+ ".tcshrc": "shell",
+ ".xonshrc": "python",
+ ".shrc": "shell",
+ ".aliases": "shell",
+ ".functions": "shell",
+ ".exports": "shell",
+ ".direnvrc": "shell",
+};
+
function CodeEditPreview({ model }: SpecializedViewProps) {
const fileContent = useAtomValue(model.fileContent);
const setNewFileContent = useSetAtom(model.newFileContent);
const fileInfo = useAtomValue(model.statFile);
+ const fileName = fileInfo?.path || fileInfo?.name;
+
+ const baseName = fileName ? fileName.split("/").pop() : null;
+ const language = baseName && shellFileMap[baseName] ? shellFileMap[baseName] : undefined;
function codeEditKeyDownHandler(e: WaveKeyboardEvent): boolean {
if (checkKeyPressed(e, "Cmd:e")) {
@@ -65,6 +90,8 @@ function CodeEditPreview({ model }: SpecializedViewProps) {
setNewFileContent(text)}
onMount={onMount}