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

improve: Move highlighted code to newly created cells #2484

Merged
merged 11 commits into from
Oct 6, 2024

Conversation

wasimsandhu
Copy link
Collaborator

@wasimsandhu wasimsandhu commented Oct 3, 2024

📝 Summary

Implements #2474.

🔍 Description of Changes

When a new cell is created, any highlighted code is cut from the original cell and pasted into the new cell.

📋 Checklist

  • I have read the contributor guidelines.
  • For large changes, or changes that affect the public API: this change was discussed or approved through an issue, on Discord, or the community discussions (Please provide a link if applicable).
  • I have added tests for the changes made.
  • I have run the code and verified that it works as expected.

📜 Reviewers

@akshayka OR @mscolnick

Sorry, something went wrong.

@wasimsandhu wasimsandhu added the enhancement New feature or request label Oct 3, 2024
@wasimsandhu wasimsandhu requested a review from mscolnick October 3, 2024 05:42
@wasimsandhu wasimsandhu self-assigned this Oct 3, 2024
Copy link

vercel bot commented Oct 3, 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 Oct 5, 2024 10:40pm
marimo-storybook ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 5, 2024 10:40pm

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 QOL improvement! One thing — after splitting, both cells should be marked as stale

@wasimsandhu
Copy link
Collaborator Author

@akshayka Good catch thanks!

@mscolnick
Copy link
Contributor

@wasimsandhu - can you verify this works with SQL and markdown? We probably have to do something similar to splitEditor. could we also write a test similar to splitEditor(utils.test.ts) and splitCell (cells.test.ts)

@@ -214,17 +216,24 @@ const {
: state.cellIds.topLevelIds.indexOf(cellId);
const insertionIndex = before ? index : index + 1;

let cellContents = code;
const cellEditorView = getCellEditorView(cellId as CellId);
Copy link
Contributor

@mscolnick mscolnick Oct 3, 2024

Choose a reason for hiding this comment

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

i think we should pass a param to createNewCell whether we should includeSelectionAsInitialCode.

we run createNewCell in many places and this would be weird for most cases (e.g. snippets, data-source panel, AI cell, etc).

could we also assert code and includeSelectionAsInitialCode are never both true? there is a typescript way to do this:

- code?: string;
+ code?: string | {type: 'from-selection', cellId: CellId}

Copy link
Collaborator Author

@wasimsandhu wasimsandhu Oct 4, 2024

Choose a reason for hiding this comment

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

edit: Implemented includeSelectionAsInitialCode, but not sure I understand the type for code

@wasimsandhu
Copy link
Collaborator Author

can you verify this works with SQL and markdown?

When editing a SQL/markdown cell and triggering a create new cell above/below (via button or shortcut), a Python cell is created. Do we want to change this behavior so that a cell of the same type is created? (This makes sense to me.)

@mscolnick
Copy link
Contributor

When editing a SQL/markdown cell and triggering a create new cell above/below (via button or shortcut), a Python cell is created. Do we want to change this behavior so that a cell of the same type is created? (This makes sense to me.)

This might take some getting used to. I would keep it python for new cells, but keep the same language for "yanked" cells. thoughts? is that weird ux?

const cellEditorView = getCellEditorView(id);
if (cellEditorView) {
const [highlighted, leftover] = extractHighlightedCode(cellEditorView);
cellContents = highlighted;
Copy link
Contributor

Choose a reason for hiding this comment

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

we should only do this this if highlighted is not empty

Copy link
Contributor

Choose a reason for hiding this comment

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

can you add a couple test cases for this?

  1. createCell when includeSelectionAsInitialCode is true and there is selection
  2. createCell when includeSelectionAsInitialCode is false and there is selection
  3. createCell when includeSelectionAsInitialCode is true and there is no selection
  4. createCell when includeSelectionAsInitialCode is false and there is no selection

Copy link
Contributor

Choose a reason for hiding this comment

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

i think it will catch small bugs like state.cellData[id].edited=true being set incorrectly.

also, doing state.cellData[id].edited is mutable, we will need to be immutable when using react.

state.cellData = {
   ...state.cellData,
   [id] : {
     ...state.cellData[id],
     code: ...,
     edited: ...
   }
}

@wasimsandhu
Copy link
Collaborator Author

This might take some getting used to. I would keep it python for new cells, but keep the same language for "yanked" cells.

Works for me!

@@ -1276,4 +1278,130 @@ describe("cell reducer", () => {
const cell = cells[0];
expect(cell.consoleOutputs).toEqual([STDOUT1, STDOUT2]);
});

it("can create a cell using selected code", () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

can you put each of these in there own tests and share setup code?

describe("can create a cell using selected code"

  beforeEach(() => {
   // setup code

  })

  it("can create when includeSelectionAsInitialCode is true and there is selection", () => {
    ...test one
   })
   ...
});

this makes it easier to follow given the same initial setup.

could you also:

  1. verify edited state
  2. do a test with markdown includeSelectionAsInitialCode - i noticed a bug when i add a cell above/below a markdown cell with includeSelectionAsInitialCode=true, it says it is edited

[id]: {
...state.cellData[id],
code: leftover,
edited: true,
Copy link
Contributor

Choose a reason for hiding this comment

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

this might need to be edited: Boolean(leftover) && state.cellData[id].code !== state.cellData[id].code,

i noticed a bug with markdown with no selection being made stale, it would be great to prove this in a test: get the test to fail first and then fix this code so the tests passes

Copy link
Contributor

Choose a reason for hiding this comment

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

made a suggestion above that you may not need this.

expect(highlighted).toEqual(thirdLine);
expect(leftover).toEqual(`${firstLine}\n${secondLine}`);
});
});
Copy link
Contributor

Choose a reason for hiding this comment

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

can you write some tests for markdown and sql?

  1. sql x no selection
  2. sql x with selection
  3. markdown x no selection
  4. markdown x with selection

const editorView = state.cellHandles[id].current?.editorView;
if (editorView) {
const [highlighted, leftover] = extractHighlightedCode(editorView);
if (highlighted.length > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

i think the issue is that for markdown/sql, highlighted > 0. if you write a test for extractHighlightedCode, can we get verify that no selection -> no highlighted


export function extractHighlightedCode(editor: EditorView) {
const code = editor.state.doc.toString();
let { from, to } = editor.state.selection.main;
Copy link
Contributor

Choose a reason for hiding this comment

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

you could for if (from === to) {return ["", code]

Copy link
Contributor

Choose a reason for hiding this comment

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

or could do if (from === to) {return null to signify nothing was highlighted. it will force consumers of this downstream to check null.

i think that is better / clearer

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Implemented this and it seems to have fixed the stale issue

Copy link
Contributor

@mscolnick mscolnick left a comment

Choose a reason for hiding this comment

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

awesome work!

@mscolnick mscolnick merged commit 25afc55 into main Oct 6, 2024
22 checks passed
@mscolnick mscolnick deleted the wasim/split-highlighted-code branch October 6, 2024 01:21
Copy link

github-actions bot commented Oct 6, 2024

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

akshayka added a commit that referenced this pull request Oct 8, 2024
This reverts commit 25afc55.

After some experimentation we decided that moving highlighted code
to newly created cells is not intuitive. It's common to have code
highlighted without an intention to split the cell. Splitting is
destructive because it marks cells as stale, so it should be something
that is done explicitly by the user -- either by the split hotkey
or by simply copy pasting.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants