Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<div id="editor-bar">
<button class="purple-button btn-new">New<i class="fa-solid fa-plus"></i></button>
<button class="purple-button btn-open">Open<i class="fa-solid fa-folder-open"></i></button>
<button class="purple-button btn-format">Format<i class="fa-solid fa-wand-magic-sparkles"></i></button>
<button class="purple-button btn-save">Save<i class="fa-solid fa-floppy-disk"></i></button>
<button class="purple-button btn-save-as">Save As<i class="fa-solid fa-download"></i></button>
<div class="file-path"></div>
Expand All @@ -85,6 +86,7 @@
<ul>
<li><a class="btn-new">New<i class="fa-solid fa-plus"></i></a></li>
<li><a class="btn-open">Open<i class="fa-solid fa-folder-open"></i></a></li>
<li><a class="btn-format">Format<i class="fa-solid fa-wand-magic-sparkles"></i></a></li>
<li><a class="btn-save">Save<i class="fa-solid fa-floppy-disk"></i></a></li>
<li><a class="btn-save-as">Save As<i class="fa-solid fa-download"></i></a></li>
</ul>
Expand Down
79 changes: 79 additions & 0 deletions js/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { xml } from "@codemirror/lang-xml";
import { markdown } from "@codemirror/lang-markdown";
import { syntaxHighlighting, indentUnit } from "@codemirror/language";
import { classHighlighter } from "@lezer/highlight";
import initRuffFormatter, { PositionEncoding, Workspace } from "@astral-sh/ruff-wasm-web";
import { circuitpythonHighlight } from "./common/circuitpython_highlight.js";
import { getFileIcon } from "./common/file_dialog.js";

Expand Down Expand Up @@ -40,6 +41,9 @@ let workflow = null;
let unchanged = 0;
let connectionPromise = null;
let debugMessageAnsi = null;
let formatterInitPromise = null;
let formatterWorkspace = null;
let currentEditorPath = null;

const btnRestart = document.querySelector('.btn-restart');
const btnHalt = document.querySelector('.btn-halt');
Expand All @@ -48,6 +52,7 @@ const btnClear = document.querySelector('.btn-clear');
const btnConnect = document.querySelectorAll('.btn-connect');
const btnNew = document.querySelectorAll('.btn-new');
const btnOpen = document.querySelectorAll('.btn-open');
const btnFormat = document.querySelectorAll('.btn-format');
const btnSave = document.querySelectorAll('.btn-save');
const btnSaveAs = document.querySelectorAll('.btn-save-as');
const btnSaveRun = document.querySelectorAll('.btn-save-run');
Expand Down Expand Up @@ -112,6 +117,21 @@ function getFileExtensionFromPath(path) {
return base.split(".").pop().toLowerCase();
}

function isPythonFilePath(path) {
if (path === null || path === undefined) {
return true;
}
return getFileExtensionFromPath(path) === "py";
}

function updateFormatterButtonState(path) {
const enabled = isPythonFilePath(path);
btnFormat.forEach((element) => {
element.disabled = !enabled;
element.setAttribute("aria-disabled", enabled ? "false" : "true");
});
}

// Pick the CodeMirror language extensions to use for a given file path.
// Returns an array so callers can spread it directly into the editor's
// extension list. New (untitled) docs default to Python so the editor
Expand Down Expand Up @@ -211,6 +231,15 @@ btnOpen.forEach((element) => {
});
});

// Format Link/Button (Mobile and Desktop Layout)
btnFormat.forEach((element) => {
element.addEventListener('click', async function(e) {
e.preventDefault();
e.stopPropagation();
await formatCurrentFile();
});
});

// Save Link/Button (Mobile and Desktop Layout)
btnSave.forEach((element) => {
element.addEventListener('click', async function(e) {
Expand Down Expand Up @@ -301,6 +330,53 @@ async function openFile() {
}
}

async function initFormatter() {
if (!formatterInitPromise) {
formatterInitPromise = initRuffFormatter().then(() => {
formatterWorkspace = new Workspace(
{
"line-length": 88,
"indent-width": 4,
format: {
"indent-style": "space",
"quote-style": "double",
},
},
PositionEncoding.Utf16,
);
});
}
return formatterInitPromise;
}

async function formatCurrentFile() {
if (!isPythonFilePath(currentEditorPath)) {
await showMessage("Format is only available for Python files.");
return false;
}

try {
await initFormatter();
const contents = editor.state.doc.sliceString(0);
const formatted = formatterWorkspace.format(contents);

if (formatted !== contents) {
editor.dispatch({
changes: {
from: 0,
to: editor.state.doc.length,
insert: formatted,
},
});
}
return true;
} catch (e) {
console.error("Could not format Python file", e);
await showMessage(`Could not format Python file. ${e.message || e}`);
return false;
}
}

async function saveFile() {
if (await checkConnected()) {
await workflow.saveFile();
Expand Down Expand Up @@ -436,6 +512,9 @@ async function checkReadOnly() {

/* Update the filename and update the UI */
function setFilename(path) {
currentEditorPath = path;
updateFormatterButtonState(path);

// Refresh the CodeMirror language plugin whenever the active file
// changes — this is the single chokepoint that all filename
// changes route through (Open File, New File, Save As, backend
Expand Down
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"dependencies": {
"@adafruit/ble-file-transfer-js": "adafruit/ble-file-transfer-js#1.0.5",
"@adafruit/circuitpython-repl-js": "adafruit/circuitpython-repl-js#3.3.0",
"@astral-sh/ruff-wasm-web": "^0.15.21",
"@codemirror/lang-css": "^6.3.1",
"@codemirror/lang-html": "^6.4.11",
"@codemirror/lang-javascript": "^6.2.5",
Expand Down