Repository: astral-sh/ruff
File: playground/ty/src/Editor/SecondaryPanel.tsx (TypeScript)

Code before:
                readOnly: true,
                minimap: { enabled: false },
                fontSize: 14,
                roundedSelection: false,
                scrollBeyondLastLine: false,
                contextmenu: false,
              }}
              language={language}
              value={result.content}
              theme={theme === "light" ? "Ayu-Light" : "Ayu-Dark"}
            />
          </div>
        );
      case "error":
        return (
          <div className="flex-grow">
            <code className="whitespace-pre-wrap text-gray-900 dark:text-gray-100">
              {result.error}
            </code>
          </div>
        );
    }
  }
}

const PYODIDE_HOME = "/home/pyodide/";

function Run({ files, theme }: { files: ReadonlyFiles; theme: Theme }) {
  const [runOutput, setRunOutput] = useState<Promise<string> | null>(null);
  const handleRun = () => {
    const output = (async () => {
      const pyodide = await loadPyodide();

      let combined_output = "";

      const outputHandler = (output: string) => {
        combined_output += output + "\n";
      };

      pyodide.setStdout({ batched: outputHandler });
      pyodide.setStderr({ batched: outputHandler });

      const main = files.selected == null ? "" : files.contents[files.selected];

      let fileName = "main.py";
      for (const file of files.index) {
        const last_separator = file.name.lastIndexOf("/");

        if (last_separator !== -1) {
          const directory = PYODIDE_HOME + file.name.slice(0, last_separator);
          pyodide.FS.mkdirTree(directory);

Review comment (suggestion):
To be less dependent on pyodide:

We could set the home path when loading pyodide, see https://pyodide.org/en/stable/usage/api/js-api.html#exports.PyodideConfig.env

Code after:
                readOnly: true,
                minimap: { enabled: false },
                fontSize: 14,
                roundedSelection: false,
                scrollBeyondLastLine: false,
                contextmenu: false,
              }}
              language={language}
              value={result.content}
              theme={theme === "light" ? "Ayu-Light" : "Ayu-Dark"}
            />
          </div>
        );
      case "error":
        return (
          <div className="flex-grow">
            <code className="whitespace-pre-wrap text-gray-900 dark:text-gray-100">
              {result.error}
            </code>
          </div>
        );
    }
  }
}

const SANDBOX_BASE_DIRECTORY = "/playground/";

function Run({ files, theme }: { files: ReadonlyFiles; theme: Theme }) {
  const [runOutput, setRunOutput] = useState<Promise<string> | null>(null);
  const handleRun = () => {
    const output = (async () => {
      const pyodide = await loadPyodide({
        env: {
          HOME: SANDBOX_BASE_DIRECTORY,
        },
      });

      let combined_output = "";

      const outputHandler = (output: string) => {
        combined_output += output + "\n";
      };

      pyodide.setStdout({ batched: outputHandler });
      pyodide.setStderr({ batched: outputHandler });

      const main = files.selected == null ? "" : files.contents[files.selected];

      let fileName = "main.py";
      for (const file of files.index) {
        const last_separator = file.name.lastIndexOf("/");