ckeditor5 icon indicating copy to clipboard operation
ckeditor5 copied to clipboard

Cmd+Delete on MacOS (delete the line) doesn't work

Open gauravjain028 opened this issue 7 years ago • 11 comments

Is this a bug report or feature request? (choose one)

🐞 Bug report

💻 Version of CKEditor

11.0.1

📋 Steps to reproduce

  1. Add few lines of content.
  2. Press cmd+delete on Mac

✅ Expected result

It should Remove the current line where the cursor was.

❎ Actual result

It is removing only one character, just like normal Delete works.

📃 Other details that might be useful

Should be checked Macbook.

gauravjain028 avatar Sep 04 '18 07:09 gauravjain028

On Mac it works with Alt (option). It was by design or is it a bug?

cc: @jodator

pomek avatar Sep 04 '18 08:09 pomek

I checked, Alt + Delete removes a word not the line.

gauravjain028 avatar Sep 04 '18 09:09 gauravjain028

Oh, right. The editor does not support remove whole line at this moment.

jodator avatar Sep 04 '18 09:09 jodator

We don't support "remove the line" and due to technical limitations, we may not be able to quickly implement it. Implementing "remove the word" was possible based on some heuristic (although, it's not perfect for sure).

With remove the line there are two options:

  • Implement an algorithm which is able to translate the "end of line" to a position in the text. IDK if this is doable and if it is, it may be quite complex.
  • Don't handle Cmd+Delete and see what the browser will do (listen to mutations or just check the state after). Then, redo that browser's action and apply a similar change to the model. We do it this way on Android where there's no keyCode so we need to learn stuff from the mutations.

Reinmar avatar Sep 04 '18 09:09 Reinmar

Note that we currently consider this a pretty big problem, since a large fraction of our users seem to rely heavily on having access to Cmd+Delete for their text-editing workflow. Importantly, CMD-Shift-Left does already select the text on the current line, so maybe there is some way of leveraging that into a line-delete.

Discordius avatar Nov 12 '19 03:11 Discordius

Then, redo that browser's action and apply a similar change to the model.

It would actually be great to do this for Alt+Backspace as well, because on macOS the system-wide word boundary detection algorithm seems to differ from the one implemented by CKEditor.

neongreen avatar Feb 12 '21 15:02 neongreen

Are there any examples of doing this in the codebase, other than keyCode on Android?

neongreen avatar Feb 12 '21 15:02 neongreen

Any updates? Been years now... pretty annoying to have this issue on such a good editor.

hajrice avatar May 20 '22 10:05 hajrice

I wrote a small plugin for this, I am sure there will be bugs but better than nothing for somebody looking for this

import Plugin from '@ckeditor/ckeditor5-core/src/plugin'
import Element from '@ckeditor/ckeditor5-engine/src/model/element'

export default class CmdDelete extends Plugin {
  init() {
    const editor = this.editor
    const model = editor.model

    editor.editing.view.document.on(
      'keydown',
      (evt, data) => {
        const evtData = (data as any).domEvent as KeyboardEvent

        if (evtData.metaKey && evtData.key === 'Backspace') {
          // stop propagating event and prevent default
          evt.stop()
          evtData.preventDefault()
          evtData.stopImmediatePropagation()

          // get current selection's parent element
          const selection = model.document.selection
          const cursorPos = selection.getFirstPosition()
          const parent = cursorPos?.parent

          if (parent && parent instanceof Element && parent.name !== '$root') {
            model.change((writer) => {
              // take all children
              Array.from(parent.getChildren())
                // filter to children with same offset as the selection
                .filter(
                  (child) =>
                    child.endOffset! === cursorPos.offset ||
                    child.startOffset! === cursorPos.offset,
                )
                // reverse so that we start removing from the end
                .reverse()
                // using every because forEach doesnt have break and returning false works like break in every
                .every((child, index) => {
                  if (child instanceof Element && child.name === 'softBreak') {
                    // if child is element and is a soft break (shift+enter)
                    if (index !== 0) {
                      // if it is *not* the first thing that is encountered
                      // eg when the softbreak is at the end of line, user takes cursor to the end of line and presses cmd+del

                      // then break the loop and exit the plugin code
                      return false
                    }

                    // if it is the first thing seen by the code, ignore it and move to the next child
                  } else {
                    // if it is not a softbreak, remove the child
                    writer.remove(child)
                  }

                  // continue loop
                  return true
                })
              writer.insertText('', parent)
            })
          }
        }
      },
      { priority: 'highest' },
    )
  }
}

the codeblock may be outdated when you see it, here is a gist I will keep updating according to comments if any: https://gist.github.com/sudhanshu16/446183d909f0a0ccb71ef99203dffc7f

Suggestions and comments are welcomed!

sudhanshug16 avatar Jun 07 '22 12:06 sudhanshug16

Is there an update on this? We were looking for ways to make a plugin but it doesn't seem CKE keeps track of the beginning of a line inside a paragraph element.

melindastanbery avatar Aug 02 '22 21:08 melindastanbery

If it was something we could calculate easily, we would certainly implement this. It still wasn't solved because it's a browser thing to calculate such positions and we had to wait until browsers allow us to do that (which happened recently with Firefox completing support for beforeinput).

The good news is – this is already fixed on #11456. We're working right now to finish the migration to beforeinput which will include this change as well.

Reinmar avatar Aug 03 '22 08:08 Reinmar