Markdown Notebook Panes #21012

Open
opened 2026-01-31 07:30:34 +00:00 by claunia · 12 comments
Owner

Originally created by @heartacker on GitHub (Dec 23, 2023).

Pre-requisite: #997

Spec in progress in https://github.com/microsoft/terminal/blob/dev/migrie/s/north-star/doc/specs/NorthStar/Markdown%20Notebooks.md

User Stories

  • A: The user can perform some commandline action (like wt open README.md), which opens a new pane in the Terminal, with the markdown file
    rendered into that pane.
  • B: Markdown panes have buttons next to code blocks that allow the text of
    that block to be sent directly to the adjacent terminal as input.
  • C: The user can press different buttons to run some subset of all the
    commands in the file
    • C.1: Run all the commands in this file
    • C.2: Run all the commands from (the currently selected block) to the end
      of the file
    • C.1: Run all the commands from (the currently selected block) to the
      next header. (e.g., run all the commands in this section of the doc.)
  • D: The user can edit the contents of the markdown file directly in the
    Terminal.
  • E: The Terminal could be configured to automatically open a markdown file
    when cding to a directory
  • F: The command for opening a markdown file also supports opening files
    from the web (e.g. directly from GitHub)
  • G: Code blocks in the markdown file are automatically assigned
    autoincrementing IDs. The user can perform an action (via keybinding, command
    palette, whatever) to execute a command block from the file, based on it's
    assigned ID.
  • H: ...

maintainer notes: original OP below the break


Description of the new feature/enhancement

For many developers, especially embedded developers, they would pre-define many text commands and save them in a text file. If WT can split views and open and display text in one view, we can quickly send the text commands to the terminal. I can send lines, send selected blocks, or send the entire content of the file, and preset some shortcuts.

Proposed technical implementation details (optional)

image

Originally created by @heartacker on GitHub (Dec 23, 2023). Pre-requisite: #997 Spec in progress in https://github.com/microsoft/terminal/blob/dev/migrie/s/north-star/doc/specs/NorthStar/Markdown%20Notebooks.md > ### User Stories > > * **A**: The user can perform some commandline action (like `wt open > README.md`), which opens a new pane in the Terminal, with the markdown file > rendered into that pane. > * **B**: Markdown panes have buttons next to code blocks that allow the text of > that block to be sent directly to the adjacent terminal as input. > * **C**: The user can press different buttons to run some subset of all the > commands in the file > - **C.1**: Run all the commands in this file > - **C.2**: Run all the commands from (the currently selected block) to the end > of the file > - **C.1**: Run all the commands from (the currently selected block) to the > next header. (e.g., run all the commands in this section of the doc.) > * **D**: The user can edit the contents of the markdown file directly in the > Terminal. > * **E**: The Terminal could be configured to automatically open a markdown file > when `cd`ing to a directory > * **F**: The command for opening a markdown file also supports opening files > from the web (e.g. directly from GitHub) > * **G**: Code blocks in the markdown file are automatically assigned > autoincrementing IDs. The user can perform an action (via keybinding, command > palette, whatever) to execute a command block from the file, based on it's > assigned ID. > * **H**: ... _maintainer notes: original OP below the break_ ---- # Description of the new feature/enhancement <!-- A clear and concise description of what the problem is that the new feature would solve. Describe why and how a user would use this new functionality (if applicable). --> For many developers, especially embedded developers, they would pre-define many text commands and save them in a text file. If WT can split views and open and display text in one view, we can quickly send the text commands to the terminal. I can send lines, send selected blocks, or send the entire content of the file, and preset some shortcuts. # Proposed technical implementation details (optional) <!-- A clear and concise description of what you want to happen. --> ![image](https://github.com/microsoft/terminal/assets/1876302/2be7c2e4-7323-429c-b31b-58942120dec6)
claunia added the Needs-Tag-FixProduct-TerminalIssue-Scenario labels 2026-01-31 07:30:35 +00:00
Author
Owner

@zadjii commented on GitHub (Dec 23, 2023):

Guys this is totally the notebooks thing I was talking about 😉

But also, there's probably some other useful things we're working on here for "Tasks" - basically, having a big long list of sendInput actions that you can quickly activate - either through the suggestions UI, or maybe even adding a "Tasks" pane.

(we'll probably have more to say after the holidays)

@zadjii commented on GitHub (Dec 23, 2023): Guys this is **totally** the notebooks thing I was talking about 😉 But also, there's probably some other useful things we're working on here for "Tasks" - basically, having a big long list of `sendInput` actions that you can quickly activate - either through the suggestions UI, or maybe even adding a "Tasks" pane. (we'll probably have more to say after the holidays)
Author
Owner

@zadjii-msft commented on GitHub (Jan 4, 2024):

Okay so, you may be interested in the Suggestions UI and Tasks, which are new in 1.19: Using SendInput Actions in the Suggestions UI

I have Big Plans for these in upcoming releases - some of which is tracked in #13445 (though I think a better thread is floating around here somewhere)

see also:

@zadjii-msft commented on GitHub (Jan 4, 2024): Okay so, you may be interested in the Suggestions UI and Tasks, which are new in 1.19: [Using SendInput Actions in the Suggestions UI](https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-19-release/#using-sendinput-actions-in-the-suggestions-ui) ![](https://devblogs.microsoft.com/commandline/wp-content/uploads/sites/33/2023/09/SuggestionsUI.gif) I have Big Plans for these in upcoming releases - some of which is tracked in #13445 (though I think a better thread is floating around here somewhere) see also: * #1595 * #15664
Author
Owner

@heartacker commented on GitHub (Jan 4, 2024):

no, I know this, and we DO NOT want to config the setting.json, we just want to code in some text file for TeamWorks

so, we want to open the text and the send those command easily, through terminal

@heartacker commented on GitHub (Jan 4, 2024): no, I know this, and we DO NOT want to config the setting.json, we just want to code in some text file for TeamWorks so, we want to open the text and the send those command easily, through terminal
Author
Owner

@zadjii-msft commented on GitHub (Jan 4, 2024):

No worries! I've got a lot of related ideas in this space, and untangling them all is sometimes a bit tricky.

You're looking for something more like this?

Yea? A file, with blocks of code that lets you run individual commands, or the whole block?

@zadjii-msft commented on GitHub (Jan 4, 2024): No worries! I've got a lot of related ideas in this space, and untangling them all is sometimes a bit tricky. You're looking for something more like this? ![](https://raw.githubusercontent.com/microsoft/terminal/dev/migrie/s/north-star/doc/specs/NorthStar/img/mockup-000.png) Yea? A file, with blocks of code that lets you run individual commands, or the whole block?
Author
Owner

@heartacker commented on GitHub (Jan 4, 2024):

This is so innovative.
and a little simple txt file for me
We can run the line to terminal where curser focused (with shortcut )
or select some block to run

@heartacker commented on GitHub (Jan 4, 2024): This is so innovative. and a little simple txt file for me We can run the line to terminal where curser focused (with shortcut ) or select some block to run
Author
Owner

@zadjii-msft commented on GitHub (Jan 4, 2024):

Congrats, this gets to be the thread then ☺️

I've been ideating in this space for a long time, just never actually filed a thread for it. I'm gonna co-opt the OP here to add some other notes. Thanks!

@zadjii-msft commented on GitHub (Jan 4, 2024): Congrats, this gets to be the thread then ☺️ I've been ideating in this space for a long time, just never actually filed a thread for it. I'm gonna co-opt the OP here to add some other notes. Thanks!
Author
Owner

@heartacker commented on GitHub (Jan 5, 2024):

@zadjii-msft
here is some demo using vscode.(yes, we can do this with vscode)

  1. text base panel is need indeed (good for teamwork and easy to use)
  2. notebook panel is welcome also (good for guiding)

txt notebook_panel

@heartacker commented on GitHub (Jan 5, 2024): @zadjii-msft here is some demo using vscode.(yes, we can do this with vscode) 1. text base panel is need indeed (good for teamwork and easy to use) 2. notebook panel is welcome also (good for guiding) ![txt notebook_panel](https://github.com/microsoft/terminal/assets/1876302/ca2797de-5a12-4c11-8fef-bd396a46d332)
Author
Owner

@zadjii-msft commented on GitHub (Mar 7, 2024):

reserving for notes for hackathon

9da196da7d: dev/migrie/fhl/notebook-proto-000 was the eldest attempt here, circa March 2023. Notably predates tab tear out.
Actual relevant diff was: a04a51bbe4...dev/migrie/fhl/notebook-proto-000

2024 spring hack is branched off dev/migrie/fhl/2024-spring-merge-base, https://github.com/microsoft/terminal/compare/dev/migrie/fhl/2024-spring-merge-base...dev/migrie/fhl/2024-inline-notebook

Notes that I have saved locally, but should be persisted elsewhere just in case

Notes as I try to make this work

There's a lot of in-flight changes to the Terminal, so I'm gonna start off of sui-panes + dev/migrie/til-events-for-all

Main workflow: User clicks "Run" on a textblock with a command.

We want to send that to the connection.

buttonPressedHandler(auto&&,auto&&)
{
    Notebook.SendInput(block.Text());
}

notebook sends that to the ControlCore? Active TermControl? Let's start there, by sending it to the active TermControl

Control does it's thing. Eventually the command ends, and the control raises a NewPrompt

On the NewPrompt:

  • Notebook needs to cork the connection
  • Remove the connection from the TermControl.
    • Including removing old event handlers
  • Tell the TermControl to stop rendering there.
    • TermControl doesn't actually own the renderer, the ControlCore does. So plumb it.
    • Tell the Terminal
    • The TermControl can totally just keep rendering. That's fine.
  • Create a new TermControl,
    • Start by instantiating a new ExistingControlData
      • Create a new BlockRenderData. This renderdata starts at the current,new mark, and doesn't have a bottom set
      • the existing root Terminal
      • the existing connection
    • Pass that to a new ControlInteractivity/ControlCore
      • Who grabs the RenderData out of that existing control data and uses it to create a new Renderer
    • Add that content (ControlInteractivity) to a new TermControl
    • attach the connection to it
    • mark the new control as the active one.

On a CommandStarted:

This is when the control actually needs to be rendered. Raise some event that notebook can bubble to mark it as Visible

Some interfaces

class Notebook {
    Notebook(ITerminalConnection connection, Settings...);
}
class Notebook
{
    TermControl[] controls;
    TermControl active;
    ITerminalConnection connection;
    shared_ptr<Terminal> terminal;
    Notebook(ITerminalConnection connection, Settings...); // Initialize the terminal, the NotebookRenderData, and the first TermControl
    void NewPromptHandler()
}
class NotebookRenderData : IRenderData
{
}
interface IControlData
{
    IRenderData* renderData;
    Terminal* terminal;
    ITerminalConnection connection;
}
struct Control.ExistingControlData : IControlData
{
    IRenderData* renderData;
    Terminal* terminal;
    ITerminalConnection connection;
}

The IRenderData for a control is just the Terminal itself.
TextBuffer is created with a reference to a Renderer. Yike.
In the ControlCore ctor is where we construct the Renderer and pass in the Terminal as the IRenderData

Terminal already knows how to be a IRenderData so we can just modify it's implementation to also work in block mode. NO NO NO there's only one Terminal. It needs to implement a second IBlockRenderData interface, and have the control nah fuck

ControlCore::ControlCore(ExistingControlData dataFromNotebook, Settings...)
{
    _terminal = dataFromNotebook.terminal;
    _renderer = make_unique<Renderer>(renderSettings,
                                      dataFromNotebook.renderData, // IRenderData
                                      nullptr, // pEngine
                                      0,  // cEngines
                                      std::move(renderThread));

}

The notebook holds the Terminal. It holds a bunch of controls&cores. So there's one Renderer for each control. Each renderer is given a NotebookRenderData that the Notebook owns and instantiates for each control.

At creation

We instantiate a new Notebook, with the given connection and settings.

  • It's going to create a Terminal,
    • Passing in to that Terminal, it'll pass it's own renderdata?

Terminal already implements IRenderData. And on Terminal::Create(), Terminal recieves a Renderer&. That's annoying. We

  • And eventually, a first TermControl.

Todo list

  • Convert the Renderer& in TextBuffer and AdaptDispatch (et. al) to be a Renderer*, since references can't be reassigned.
  • Terminal needs a ChangeRenderer method that takes a Renderer* and updates the buffer et al.
  • Create a BlockRenderData class, (In TerminalCore project, why not)
    • implements IRenderData,
    • Takes a Terminal* as a param
    • Originally, just implement as a passthrough on all the TerminalRenderData methods
  • Change ControlCore to have a public non-projected ctor which takes a IControlData and settings, and initialize the _terminal from that if given.
  • Create a Notebook class in Terminal.Control.
    • Just stick a pair of TermControls into the notebook.

At this point, I was able to stick the pair of TermControls from the notebook into the MyPage of the scratch project.

  • De-dupe the input.
    • I think there's two OUTPUT handlers registered somewhere.
  • Update all bocks when relevant
  • Start making more blocks for each command

2024-march-14 lunch screenshot:
image

  • All blocks share one Terminal, but have different RenderData.
  • Every time we get a FTCS A, we make a new block.
    • We do this behind the scenes
  • Each block's renderdata only renders that specific mark.
  • Each block's renderdata independently tracks the viewport, so that they can be scrolled independently
  • Each block has a play button
  • Blocks are generated from markdown.
  • Markdown files can be loaded from a given file path.
Updates archive

2024-march-13 lunch screenshot:
fhl-notebooks-with-progress

2024-march-12 EoD screenshot:
image

2024-march-11 EoD screenshot:
image

2024-march-11 lunch screenshot:
image
2024-march-08 screenshot:
image

These two blocks both share a single Connection and Terminal. They have separate ControlCore & ControlInteractivity & TermControl's. Only the last one actually gets updates to its viewport, we should fix that.

Conclusions

Overall, project was a huge success. Clearly, it's possible to have Terminal notebooks that have a single hidden connection & terminal core, and then have a markdown frontend for that notebook, with each block of output rendered separately.

However, at this point, one should probably ask: why the heck isn't this just .ipynb's? Especially with the existence of:

Couldn't the Terminal just be a kernel for that? There's not really a reason why not, right? And if we want to do that, then we really don't need... any... of what was written here. I should have probably done more research first.


There's probably also still value in the side-by-side UX. Probably.

@zadjii-msft commented on GitHub (Mar 7, 2024): _reserving for notes for hackathon_ 9da196da7da7e342698a354a322cfc0265cc9d04: `dev/migrie/fhl/notebook-proto-000` was the eldest attempt here, circa March 2023. Notably predates tab tear out. Actual relevant diff was: https://github.com/microsoft/terminal/compare/a04a51bbe4270d65a5a58652772b00fb719261ac...dev/migrie/fhl/notebook-proto-000 2024 spring hack is branched off `dev/migrie/fhl/2024-spring-merge-base`, https://github.com/microsoft/terminal/compare/dev/migrie/fhl/2024-spring-merge-base...dev/migrie/fhl/2024-inline-notebook * `dev/migrie/f/sui-panes` * + til events ==> `dev/migrie/fhl/2024-spring-merge-base` * Inline notebooks: https://github.com/microsoft/terminal/compare/dev/migrie/fhl/2024-spring-merge-base...dev/migrie/fhl/2024-inline-notebook * Tasks pane: https://github.com/microsoft/terminal/compare/dev/migrie/f/sui-panes...dev/migrie/fhl/tasks-pane * Markdown pane: https://github.com/microsoft/terminal/compare/dev/migrie/f/tasks-pane...dev/migrie/fhl/md-pane <details> <summary>Notes that I have saved locally, but should be persisted elsewhere just in case</summary> Notes as I try to make this work There's a lot of in-flight changes to the Terminal, so I'm gonna start off of `sui-panes` + `dev/migrie/til-events-for-all` ## Main workflow: User clicks "Run" on a textblock with a command. We want to send that to the connection. ```c++ buttonPressedHandler(auto&&,auto&&) { Notebook.SendInput(block.Text()); } ``` notebook sends that to the `ControlCore`? Active `TermControl`? Let's start there, by sending it to the active `TermControl` Control does it's thing. Eventually the command ends, and the control raises a `NewPrompt` ### On the `NewPrompt`: * Notebook needs to cork the connection * Remove the connection from the `TermControl`. - Including removing old event handlers * ~~Tell the `TermControl` to stop rendering there.~~ - ~~`TermControl` doesn't actually own the renderer, the `ControlCore` does. So plumb it.~~ - ~~Tell the `Terminal`~~ - The TermControl can totally just keep rendering. That's fine. * Create a new `TermControl`, - Start by instantiating a new `ExistingControlData` - Create a new `BlockRenderData`. This renderdata starts at the current,new mark, and doesn't have a bottom set - the existing root `Terminal` - the existing connection - Pass that to a new ControlInteractivity/ControlCore - Who grabs the `RenderData` out of that existing control data and uses it to create a new `Renderer` - Add that content (ControlInteractivity) to a new TermControl - attach the connection to it - mark the new control as the active one. ### On a `CommandStarted`: This is when the control actually needs to be rendered. Raise some event that notebook can bubble to mark it as `Visible` ### Some interfaces ```csharp class Notebook { Notebook(ITerminalConnection connection, Settings...); } ``` ```c++ class Notebook { TermControl[] controls; TermControl active; ITerminalConnection connection; shared_ptr<Terminal> terminal; Notebook(ITerminalConnection connection, Settings...); // Initialize the terminal, the NotebookRenderData, and the first TermControl void NewPromptHandler() } class NotebookRenderData : IRenderData { } interface IControlData { IRenderData* renderData; Terminal* terminal; ITerminalConnection connection; } struct Control.ExistingControlData : IControlData { IRenderData* renderData; Terminal* terminal; ITerminalConnection connection; } ``` The `IRenderData` for a control is just the `Terminal` itself. `TextBuffer` is created with a reference to a `Renderer`. Yike. In the `ControlCore` ctor is where we construct the `Renderer` and pass in the `Terminal` as the `IRenderData` ~~`Terminal` already knows how to be a `IRenderData` so we can just modify it's implementation to also work in block mode. NO NO NO there's only one Terminal. It needs to implement a second IBlockRenderData interface, and have the control nah fuck~~ ```c++ ControlCore::ControlCore(ExistingControlData dataFromNotebook, Settings...) { _terminal = dataFromNotebook.terminal; _renderer = make_unique<Renderer>(renderSettings, dataFromNotebook.renderData, // IRenderData nullptr, // pEngine 0, // cEngines std::move(renderThread)); } ``` The notebook holds the `Terminal`. It holds a bunch of controls&cores. So there's one Renderer for each control. Each renderer is given a NotebookRenderData that the Notebook owns and instantiates for each control. ## At creation We instantiate a new `Notebook`, with the given connection and settings. - It's going to create a `Terminal`, - Passing in to that Terminal, it'll pass it's own renderdata? Terminal already implements IRenderData. And on `Terminal::Create()`, Terminal recieves a `Renderer&`. That's annoying. We - And eventually, a first `TermControl`. ## Todo list * [x] Convert the `Renderer&` in `TextBuffer` and `AdaptDispatch` (et. al) to be a `Renderer*`, since references can't be reassigned. * [x] `Terminal` needs a ChangeRenderer method that takes a `Renderer*` and updates the buffer et al. * [x] Create a `BlockRenderData` class, (In `TerminalCore` project, why not) * [x] implements `IRenderData`, * [x] Takes a `Terminal*` as a param * [x] Originally, just implement as a passthrough on all the TerminalRenderData methods * [x] Change ControlCore to have a public non-projected ctor which takes a `IControlData` and settings, and initialize the `_terminal` from that if given. * [x] Create a `Notebook` class in `Terminal.Control`. * [x] Just stick a pair of TermControls into the notebook. At this point, I was able to stick the pair of TermControls from the notebook into the `MyPage` of the scratch project. * [x] De-dupe the input. - I think there's two OUTPUT handlers registered somewhere. * [ ] Update all bocks when relevant * [ ] Start making more blocks for each command </details> _2024-march-14 lunch screenshot_: ![image](https://github.com/microsoft/terminal/assets/18356694/68444a10-ff01-45d0-8360-e78063c05246) * All blocks share one Terminal, but have different RenderData. * Every time we get a `FTCS A`, we make a new block. * We do this behind the scenes * Each block's renderdata only renders that specific mark. * Each block's renderdata independently tracks the viewport, so that they can be scrolled independently * Each block has a play button * Blocks are generated from markdown. * Markdown files can be loaded from a given file path. <details> <summary>Updates archive</summary> _2024-march-13 lunch screenshot_: ![fhl-notebooks-with-progress](https://github.com/microsoft/terminal/assets/18356694/3bd160f1-4c46-4706-a5ad-a27f201a82bc) _2024-march-12 EoD screenshot_: ![image](https://github.com/microsoft/terminal/assets/18356694/9fa11089-7f4f-4983-b211-ac4bf195b40a) _2024-march-11 EoD screenshot_: ![image](https://github.com/microsoft/terminal/assets/18356694/0c1071c1-499d-4dd9-a30a-bced9f163c24) _2024-march-11 lunch screenshot_: ![image](https://github.com/microsoft/terminal/assets/18356694/a5ffd870-2385-4d5a-a722-6d92a8fbcc95) _2024-march-08 screenshot_: ![image](https://github.com/microsoft/terminal/assets/18356694/8ad7fd1a-3bab-418e-bb73-33f8b4351b67) These two blocks both share a single `Connection` and `Terminal`. They have separate `ControlCore` & `ControlInteractivity` & `TermControl`'s. Only the last one actually gets updates to its viewport, we should fix that. </details> ## Conclusions Overall, project was a huge success. Clearly, it's possible to have Terminal notebooks that have a single hidden connection & terminal core, and then have a markdown frontend for that notebook, with each block of output rendered separately. However, at this point, one should probably ask: why the heck isn't this just `.ipynb`'s? Especially with the existence of: * https://github.com/dotnet/interactive and * [Polyglot Notebooks](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) Couldn't the Terminal just be a kernel for that? There's not really a reason why not, right? And if we want to do that, then we really don't need... any... of what was written here. I should have probably done more research first. ------------ There's probably also still value in the side-by-side UX. Probably.
Author
Owner

@zadjii-msft commented on GitHub (Mar 14, 2024):

I'm gonna leave the above comment for the "inline notebooks" investigation that eventually petered out, and use this one for side-by-side markdown in the Terminal

Branch map:

2024-march-15 end of hackathon:
fhl-markdown-open-demo

Updates archive

2024-march-14 EoD screenshot:
image

@zadjii-msft commented on GitHub (Mar 14, 2024): I'm gonna leave the above comment for the "inline notebooks" investigation that eventually petered out, and use this one for side-by-side markdown in the Terminal Branch map: * `dev/migrie/f/sui-panes` * + til events ==> `dev/migrie/fhl/2024-spring-merge-base` * **Inline notebooks**: https://github.com/microsoft/terminal/compare/dev/migrie/fhl/2024-spring-merge-base...dev/migrie/fhl/2024-inline-notebook * Tasks pane: https://github.com/microsoft/terminal/compare/dev/migrie/f/sui-panes...dev/migrie/fhl/tasks-pane * **Markdown pane**: https://github.com/microsoft/terminal/compare/dev/migrie/f/tasks-pane...dev/migrie/fhl/md-pane _2024-march-15 end of hackathon_: ![fhl-markdown-open-demo](https://github.com/microsoft/terminal/assets/18356694/3fe10b55-8d07-4183-8555-2e2538716d4a) <details> <summary>Updates archive</summary> _2024-march-14 EoD screenshot_: ![image](https://github.com/microsoft/terminal/assets/18356694/204f83af-5ea1-45ba-8b70-0e5939eb1ecb) </details>
Author
Owner

@heartacker commented on GitHub (Mar 15, 2024):

Could you please provide a another text base panel, not only markdown panel?

@heartacker commented on GitHub (Mar 15, 2024): Could you please provide a another text base panel, not only markdown panel?
Author
Owner

@zadjii-msft commented on GitHub (Mar 15, 2024):

Sure, why not. Rendering plaintext is easy comparatively to rendering markdown in WinUI 😜

fhl-markdown-open-text-file

@zadjii-msft commented on GitHub (Mar 15, 2024): Sure, why not. Rendering plaintext is _easy_ comparatively to rendering markdown in WinUI 😜 ![fhl-markdown-open-text-file](https://github.com/microsoft/terminal/assets/18356694/b8ca820b-a768-438d-8174-c58a49be0af5)
Author
Owner

@heartacker commented on GitHub (Mar 15, 2024):

Sure, why not. Rendering plaintext is easy comparatively to rendering markdown in WinUI 😜

fhl-markdown-open-text-file

thank ,now i just need a short cut to send the line command without text_selected ,or selected_text command ,

after that ,we don't need copy->paste->commit line

@heartacker commented on GitHub (Mar 15, 2024): > Sure, why not. Rendering plaintext is _easy_ comparatively to rendering markdown in WinUI 😜 > > ![fhl-markdown-open-text-file](https://github.com/microsoft/terminal/assets/18356694/b8ca820b-a768-438d-8174-c58a49be0af5) > thank ,now i just need a short cut to send the line command without text_selected ,or selected_text command , after that ,we don't need copy->paste->commit line
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#21012