emmetio / codemirror6-plugin

WIP Plugin for CodeMirror 6
40 stars 7 forks source link

Expanding in CSS with Tab #29

Closed shshaw closed 4 weeks ago

shshaw commented 3 months ago

Expansion in CSS can't be done with the Tab key when Autocomplete is enabled; it just indents the code. To expand an abbreviation, you have to select it from the autocomplete menu with the Enter key.

I'm not sure if this is an Emmet problem or with our specific CodeMirror setup, but Tab works fine in Markup.

https://github.com/user-attachments/assets/03df425e-48fa-4c01-b182-83a9a5949686

We do have Prec.high on the abbreviation tracker, so it should take precedence over the indentWithTab extension, which works fine in Markup but not in CSS.

Screenshot 2024-08-06 at 6 57 49 AM

Related:

16 #27

sergeche commented 1 month ago

In CSS, the plugin expects acceptCompletion command that should insert current completion. As docs says, the Tab key is not bound by default for a11y reasons

shshaw commented 1 month ago

What's odd is we have Tab bound correctly and working in HTML and other languages, but it doesn't work specifically in CSS.

I'll look into acceptCompletion to see if there's something we can configure to get it working right in CSS.

sergeche commented 1 month ago

Not sure if I should override Tab key on my side in this case. I think it will always run Emmet expand even if user picks another completion option

shshaw commented 1 month ago

I may have figured out a manual tab override, but it's not great.

Is there a way to detect if Emmet has an expansion / completion available from the current state?

sergeche commented 1 month ago

You can try to use pickedCompletion annotation from @codemirror/autocomplete package and get its value from transaction, like this: transaction.annotation(pickedCompletion). You can then check if it has type: 'emmet' value

shshaw commented 1 month ago

Thank you, @sergeche!

Looks like the autocomplete extension only uses Tab for snippet fields, which may not really interfere with the Emmet completion. It would be great to have an Emmet config option to allow Tab regardless of Completion (or a callback/custom logic for when to ignore Completions) in here to make it easier to keep Tab in place for style languages.

For now, see below for how I have to re-enable Tab. I have a list of the EmmetKnownSyntax values of style languages and when I activate Emmet with a specific syntax, I also add this Extension.

function expandAbbreviationWithTabInStyleLanguages(syntax: EmmetKnownSyntax) {
  if (EmmetKnownSyntaxOfStyles.has(syntax)) {
    // `Prec.highest` to ensure it's above the default `abbreviationTracker` and `indentWithTab`
    return Prec.highest(
      keymap.of([
        {
          key: 'Tab',
          run: styleLanguagesTabKeyHandler
        }
      ])
    );
  }

  return [];
}

const styleLanguagesTabKeyHandler: Command = (view: EditorView) => {
  const { state } = view;
  if (completionStatus(state) === 'active') {
    expandAbbreviation(view);
    return true;
  }

  // Return false to allow the default Tab behavior
  return false;
};
sergeche commented 1 month ago

I’ve just added a new autocompleteTab option in v0.4.0. You can specify syntaxes where Emmet can apply its own completion with Tab, see main.ts for example

shshaw commented 4 weeks ago

The new option is working as expected. Gracias!