Skip to content

✨ Snippets #1623

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

Open
austincondiff opened this issue Mar 14, 2024 · 0 comments
Open

✨ Snippets #1623

austincondiff opened this issue Mar 14, 2024 · 0 comments
Labels
enhancement New feature or request extensions Issues related to the extension architecture in CodeEdit snippets toolbar

Comments

@austincondiff
Copy link
Collaborator

austincondiff commented Mar 14, 2024

Description

Users should be able to make and insert code snippets to insert into their open file at the current cursor position.

Snippets should be able to support wildcards.

Snippets should have a completion, so when a set of characters are typed within a given scope, it will suggest the snippet without having to open the Snippets overlay.

Additionally, extensions should be able to add snippets.

We might include this in a larger library feature at a later point in time.

The snippets/library overlay could be accessed by a keyboard shortcut and/or a plus icon button in the toolbar.

Note

There may require additional functionality to be build into CodeEditSourceEditor to support some of this, so we may need to do some of this after this is done.

Blockers

  • CodeEditSourceEditor completion service and menu
  • CodeEditSourceEditor wildcard support

Screenshots

Screenshot 2024-03-14 at 2 34 06 PM image Screenshot 2024-03-14 at 2 36 13 PM
@austincondiff austincondiff added the enhancement New feature or request label Mar 14, 2024
@github-actions github-actions bot added extensions Issues related to the extension architecture in CodeEdit toolbar triage needed labels Mar 14, 2024
@austincondiff austincondiff moved this from 🆕 New to 📋 Todo in CodeEdit Project Mar 14, 2024
thecoolwinter added a commit to CodeEditApp/CodeEditTextView that referenced this issue May 9, 2025
### Description

Adds an API for creating "text attachments". Essentially, views that replace ranges of text and act as a single character in typesetting, layout, and selection.

#### Detailed Changes

Text layout consists of two steps:

- Laying out whole lines
- Typesetting line fragments

The changes in this PR mostly consist of changes to the typesetting step. This step breaks down a line of text into fragments that fit into a constrained width. Text attachments are built by making 'runs' of content in that typesetting step.

> These are intentionally kept separate from the text storage. If these modifications were in the storage object, they'd be shared between editors that share storage objects. Putting these in the layout system means that a user can fold lines in one editor, and view them normally in another.

- Text attachments:
  - **New** `TextAttachment` protocol. A generic type that can draw it's contents in a line.
  - **New** `AnyTextAttachment` helps type-erase `any TextAttachment` and has a `range` for CETV to use. Very similar to `AnyHashable` or `AnyView`.
  - **New** `TextAttachmentManager` manages an ordered array of attachments, and manages hiding and showing text lines as needed, as well as invalidating layout when modifications happen.
- `TextLayoutManager` changes:
  - Added a new `determineVisiblePosition` method. This method takes in a line position and returns a new (potentially larger) position by merging lines covered by attachments. This is the foundational method for merging lines that attachments cover.
  - Removing the existing `Iterator`.
  - Added two iterators, `YPositionIterator` and `RangeIterator` that iterate over a range of y positions and text offsets, respectively. These iterators are now used by the `layoutLines` method to merge lines that have attachments and not layout hidden lines.
- Typesetting:
  - `Typesetter.swift` is marked as new, but that's because it's drastically changed.
    - `Typesetter` still performs typesetting on a text line, but it now takes into account attachments. It breaks the line into content runs, then calculates line fragments using those runs and a constrained width.
  - `TypesetContext` and `LineFragmentTypesetContext` represent partial parsing states while typesetting. They're both used once during typesetting and then discarded. Keeping them in their own structs makes `Typesetter` much more readable.
  - `CTLineTypesetData` was previously represented by a tuple, but a struct makes things clearer. It represents layout information received from a `CTTypesetter` for a `CTLine`.
  - Line break suggestion methods moved to a `CTTypesetter` extension. Each method was taking a `typesetter` argument, so moving to an extension makes them more ergonomic.
    - The only change to these methods was a change from passing a `startOffset` to instead pass a `subrange` that the typesetter finds line breaks in.
- `LineFragment`
  - Line fragments now have to manage a series of content runs that can be either attachments or plain text.
  - Drawing methods have been updated to loop over runs and draw them.
  - Position fetching methods now take into account attachments as well as text positions.
- Scroll view listeners - *this could have been a different PR but it's a small change, sorry!*.
  -  Fixed up the way the text view found it's enclosing scroll view, and listens to scroll changes.

#### Testing

- Added typesetting tests for attachments.
- Added layout manager tests.
  - Iteration
  - Invalidation
  - Attachments

### Related Issues

* CodeEditApp/CodeEditSourceEditor#43
* CodeEditApp/CodeEditSourceEditor#287
* CodeEditApp/CodeEdit#1623

### Checklist

- [x] I read and understood the [contributing guide](https://github.com/CodeEditApp/CodeEdit/blob/main/CONTRIBUTING.md) as well as the [code of conduct](https://github.com/CodeEditApp/CodeEdit/blob/main/CODE_OF_CONDUCT.md)
- [x] The issues this PR addresses are related to each other
- [x] My changes generate no new warnings
- [x] My code builds and runs on my machine
- [x] My changes are all related to the related issue above
- [x] I documented my code

### Screenshots

> Demo menu item was a testing menu item, it either adds a demo attachment to the selected range, or removes selected attachments (if any are selected). It's not included in this PR.

To test the changes like in the demo video replace `TextView+Menu.swift` with this:
<details><summary>`TextView+Menu.swift`</summary>
<p>

```swift
//
//  TextView+Menu.swift
//  CodeEditTextView
//
//  Created by Khan Winter on 8/21/23.
//

import AppKit

extension TextView {
    override public func menu(for event: NSEvent) -> NSMenu? {
        guard event.type == .rightMouseDown else { return nil }

        let menu = NSMenu()

        menu.items = [
            NSMenuItem(title: "Cut", action: #selector(cut(_:)), keyEquivalent: "x"),
            NSMenuItem(title: "Copy", action: #selector(copy(_:)), keyEquivalent: "c"),
            NSMenuItem(title: "Paste", action: #selector(paste(_:)), keyEquivalent: "v"),
            NSMenuItem(title: "Attach", action: #selector(toggleAttachmentAtSelection), keyEquivalent: "b")
        ]

        return menu
    }

    class DemoAttachment: TextAttachment {
        var width: CGFloat = 100

        func draw(in context: CGContext, rect: NSRect) {
            context.setFillColor(NSColor.red.cgColor)
            context.fill(rect)
        }
    }

    @objc func toggleAttachmentAtSelection() {
        if layoutManager.attachments.get(
            startingIn: selectedRange()
        ).first?.range.location == selectedRange().location {
            layoutManager.attachments.remove(atOffset: selectedRange().location)
        } else {
            layoutManager.attachments.add(DemoAttachment(), for: selectedRange())
        }
    }
}

```

</p>
</details> 


https://github.com/user-attachments/assets/b178fe13-d5d2-4e3d-aa55-f913df1d6c4b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request extensions Issues related to the extension architecture in CodeEdit snippets toolbar
Projects
Status: 📋 Todo
Development

No branches or pull requests

1 participant