Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: auto-import marimo for markdown #1404

Merged
merged 7 commits into from
May 20, 2024
Merged

feat: auto-import marimo for markdown #1404

merged 7 commits into from
May 20, 2024

Conversation

mscolnick
Copy link
Contributor

@mscolnick mscolnick commented May 17, 2024

This will auto-import import marimo as mo after toggling markdown

Copy link

vercel bot commented May 17, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
marimo-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 20, 2024 6:03pm
marimo-storybook ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 20, 2024 6:03pm

Copy link
Contributor

@akshayka akshayka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid a flash of NameError -> new cell -> re-running the markdown, I suggest specializing this only to markdown actions in the frontend, and doing the logic in the frontend as well, without running any code.

When the user clicks "Create Markdown" or "View as Markdown" ...

  1. Check for import[ \t]+marimo[ \t]+as[ \t]+mo across all cells.
  2. Check for mo in the variables table.
  3. If import marimo is not found, and mo is not in the variables table, then add a new cell with import marimo as mo to the top of the notebook. If autorun on startup is enabled, run it.
  4. Add the markdown cell.

1 and 2 should be inexpensive operations, so I wouldn't worry about overhead.

This hotfix is really only needed for markdown anyway. When typing Python, a NameError for mo is readily understood and fixed by the user.

@mscolnick mscolnick changed the title poc: add missing marimo import feat: auto-import marimo for markdown May 19, 2024
@mscolnick mscolnick requested a review from akshayka May 19, 2024 17:13
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @mscolnick - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟡 General issues: 3 issues found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment to tell me if it was helpful.

@@ -22,708 +22,722 @@ import { createReducerAndAtoms } from "../../utils/createReducer";
import { arrayInsert, arrayDelete } from "@/utils/arrays";
import { foldAllBulk, unfoldAllBulk } from "../codemirror/editing/commands";
import { mergeOutlines } from "../dom/outline";
import { CellHandle } from "@/components/editor/Cell";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Use of 'type' keyword for imports

The use of the 'type' keyword for importing types is a good practice as it helps in distinguishing between value imports and type imports. This can also potentially reduce the bundle size if the type is not used at runtime.

import { Logger } from "@/utils/Logger";
import { Objects } from "@/utils/objects";
import { splitAtom, selectAtom } from "jotai/utils";
import { isStaticNotebook, parseStaticState } from "../static/static-state";
import { CellLog, getCellLogsForMessage } from "./logs";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Use of 'type' keyword for imports

The use of the 'type' keyword for importing types is a good practice as it helps in distinguishing between value imports and type imports. This can also potentially reduce the bundle size if the type is not used at runtime.

Suggested change
import { CellLog, getCellLogsForMessage } from "./logs";
import { type CellLog } from "./logs";
import { getCellLogsForMessage } from "./logs";

import { deserializeBase64, deserializeJson } from "@/utils/json/base64";
import { historyField } from "@codemirror/commands";
import { clamp } from "@/utils/math";
import { LayoutState } from "../layout/layout";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Use of 'type' keyword for imports

The use of the 'type' keyword for importing types is a good practice as it helps in distinguishing between value imports and type imports. This can also potentially reduce the bundle size if the type is not used at runtime.

};
},
deleteCell: (state, action: { cellId: CellId }) => {
const cellId = action.cellId;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Prefer object destructuring when accessing and using properties. (use-object-destructuring)

Suggested change
const cellId = action.cellId;
const {cellId} = action;


ExplanationObject destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the Airbnb Javascript Style Guide

},
scrollToTarget: (state) => {
// Scroll to the specified cell and clear the scroll key.
const scrollKey = state.scrollKey;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Prefer object destructuring when accessing and using properties. (use-object-destructuring)

Suggested change
const scrollKey = state.scrollKey;
const {scrollKey} = state;


ExplanationObject destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the Airbnb Javascript Style Guide

Comment on lines 751 to 775
const errors = cellIds
.map((cellId) => {
const cell = cellRuntime[cellId];
const { name } = cellData[cellId];
if (cell.output?.mimetype === "application/vnd.marimo+error") {
// Filter out ancestor-stopped errors
// These are errors that are caused by a cell that was stopped,
// but nothing the user can take action on.
const nonAncestorErrors = cell.output.data.filter(
(error) => error.type !== "ancestor-stopped",
);

if (nonAncestorErrors.length > 0) {
return {
output: { ...cell.output, data: nonAncestorErrors },
cellId: cellId,
cellName: name,
};
}
}

return null;
})
.filter(Boolean);
return errors;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (code-quality): Inline variable that is immediately returned (inline-immediately-returned-variable)

Suggested change
const errors = cellIds
.map((cellId) => {
const cell = cellRuntime[cellId];
const { name } = cellData[cellId];
if (cell.output?.mimetype === "application/vnd.marimo+error") {
// Filter out ancestor-stopped errors
// These are errors that are caused by a cell that was stopped,
// but nothing the user can take action on.
const nonAncestorErrors = cell.output.data.filter(
(error) => error.type !== "ancestor-stopped",
);
if (nonAncestorErrors.length > 0) {
return {
output: { ...cell.output, data: nonAncestorErrors },
cellId: cellId,
cellName: name,
};
}
}
return null;
})
.filter(Boolean);
return errors;
return cellIds
.map((cellId) => {
const cell = cellRuntime[cellId];
const { name } = cellData[cellId];
if (cell.output?.mimetype === "application/vnd.marimo+error") {
// Filter out ancestor-stopped errors
// These are errors that are caused by a cell that was stopped,
// but nothing the user can take action on.
const nonAncestorErrors = cell.output.data.filter(
(error) => error.type !== "ancestor-stopped",
);
if (nonAncestorErrors.length > 0) {
return {
output: { ...cell.output, data: nonAncestorErrors },
cellId: cellId,
cellName: name,
};
}
}
return null;
})
.filter(Boolean);


ExplanationSomething that we often see in people's code is assigning to a result variable
and then immediately returning it.

Returning the result directly shortens the code and removes an unnecessary
variable, reducing the mental load of reading the function.

Where intermediate variables can be useful is if they then get used as a
parameter or a condition, and the name can act like a comment on what the
variable represents. In the case where you're returning it from a function, the
function name is there to tell you what the result is, so the variable name
is unnecessary.

Copy link
Contributor

@akshayka akshayka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, feels pretty good. Except the newly added cell shouldn't be marked as stale when it's autorun:

image

@mscolnick mscolnick merged commit fe2c2a5 into main May 20, 2024
14 of 29 checks passed
@mscolnick mscolnick deleted the ms/add-missing-import branch May 20, 2024 18:13
Copy link

🚀 Development release published. You may be able to view the changes at https://marimo.app?v=0.6.1-dev9

mscolnick added a commit that referenced this pull request May 20, 2024
* feat: auto-import marimo for markdown

* format

* lint

* fixes

* ci

* fix

* fix
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants