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

Suggested feature: delete all lines in selection #13921

Open
victorel-petrovich opened this issue Jul 23, 2023 · 37 comments
Open

Suggested feature: delete all lines in selection #13921

victorel-petrovich opened this issue Jul 23, 2023 · 37 comments

Comments

@victorel-petrovich
Copy link

victorel-petrovich commented Jul 23, 2023

Currently, it's only possible to quickly delete a single line (with a shortcut for "SCI_LINEDELETE").
In some other editor I would select several lines (even if not strictly from begin to end of lines) and press a single shortcut to delete all of those lines, in entirety.
It would work similar to how it's possible to cut or copy several selected lines: delete all lines "colored" by selection and including the one where the cursor is.

I used it quite often.

@alankilborn
Copy link
Contributor

I'd call this a "sloppy selection deletion of lines" -- you don't want to go to the precise effort of fussily selecting from col 1 of the first line to col 1 of the first line BEYOND the one you intend to delete.

I sense you're not a big fan of mouse operations, but the mouse workaround for this is to click+drag in the line number margin to select entire lines.

@alankilborn
Copy link
Contributor

If you're interested in scripting, here's one (I call it SelectWholeLinesPartiallyTouched.py) that will re-form your partial-line selection into a selection that starts and ends on line boundaries. You could tie this to a keycombo (suggest: Ctrl+Alt+Shift+w). You could hit this keycombo before a delete/copy/cut action.

# -*- coding: utf-8 -*-
from __future__ import print_function

#########################################
#
#  SelectWholeLinesPartiallyTouched (SWLPT)
#
#########################################

# references:
#  see https://github.com/notepad-plus-plus/notepad-plus-plus/issues/13921 "Suggested feature: delete all lines in selection"
#  for newbie info on PythonScripts, see https://community.notepad-plus-plus.org/topic/23039/faq-desk-how-to-install-and-run-a-script-in-pythonscript

# note: will extend the selection downward one line at a time if run repeatedly
#  (probably this feature is not useful in the multiple disjointed stream selection case)

#-------------------------------------------------------------------------------

from Npp import *

#-------------------------------------------------------------------------------

class SWLPT(object):

    def __init__(self):

        rect_sel_mode = editor.getSelectionMode() in [ SELECTIONMODE.RECTANGLE, SELECTIONMODE.THIN ]

        if editor.getSelections() > 1 and not rect_sel_mode:

            # more than one stream selection; "multi-editing" must be enabled

            for s in range(editor.getSelections()):
                p1 = editor.getSelectionNStart(s)
                p2 = editor.getSelectionNEnd(s)
                if p1 > p2: (p1, p2) = (p2, p1)  # swap
                l1 = editor.lineFromPosition(p2) + 1
                l2 = editor.lineFromPosition(p1)
                if s == 0:
                    editor.setSelection(editor.positionFromLine(l1), editor.positionFromLine(l2))
                else:
                    editor.addSelection(editor.positionFromLine(l1), editor.positionFromLine(l2))

        else:

            if rect_sel_mode:

                p1 = editor.getSelectionNStart(0)
                p2 = editor.getSelectionNEnd(editor.getSelections() - 1)
                if p1 > p2: (p1, p2) = (p2, p1)  # swap
                l1 = editor.lineFromPosition(p2) + 1
                l2 = editor.lineFromPosition(p1)

            else:

                l1 = editor.lineFromPosition(editor.getSelectionEnd()) + 1
                l2 = editor.lineFromPosition(editor.getSelectionStart())

            editor.setSelection(
                editor.positionFromLine(l1),
                editor.positionFromLine(l2)
            )

        p = editor.getSelectionNEnd(editor.getMainSelection())
        editor.scrollRange(p, p)

        editor.chooseCaretX()

#-------------------------------------------------------------------------------

if __name__ == '__main__': SWLPT()

@victorel-petrovich
Copy link
Author

victorel-petrovich commented Jul 23, 2023

I sense you're not a big fan of mouse operations, but the mouse workaround for this is to click+drag in the line number margin to select entire lines.

Right, I'm not. Besides, I usually disable that margin, and even if not- selection with keyboard is a bit faster if your fingers are already on keyboards.

@alankilborn
Copy link
Contributor

The script is the way to go for keyboardists, as running a script can be bound to a keycombo.

@victorel-petrovich
Copy link
Author

victorel-petrovich commented Jul 24, 2023

I appreciate you writing that script, I will look into it, but to be really useful: it needs to be combined with "delete" operation so that so that to be triggered by a single shortcut. Just like you can already "copy" or "cut" lines in selection with a shortcut bound to "SCI_LINECOPY" and "SCI_LINECUT".

However, I still believe this issue would not be quite solved.
It's better to have this function built-in, because: it's natural to for a function on a single element to be extended on several of same kind. Just like "copy"/"cut" of selected lines is built-in.
(Even though perhaps it should have been Scintilla to have implemented this for deleting selected lines as well...).

@alankilborn
Copy link
Contributor

alankilborn commented Jul 24, 2023

I appreciate you writing that script

I already had the script.

but to be really useful

It IS useful; I use it often.

(needs to be) triggered by a single shortcut

No, because that lessens its utility, because you don't always want to delete, sometimes you want to copy or cut... as you go on to point out.

If you REALLY want to wrap all of the functionality together, at the end of the script's logic for making the selection, simply add editor.clear() (... or editor.cut() ... or editor.copy())

It's better to have this function built-in

Well...sure. But apparently you are joining a long line of "script whiners" (definition: those who could have the functionality -- or, close to it -- they want RIGHT NOW, but decline because that functionality isn't built-in, and then goes on to wait, perhaps forever, for that functionality to become native).
It matters not to me. Cheers!

@victorel-petrovich
Copy link
Author

victorel-petrovich commented Jul 25, 2023

No, because that lessens its utility, because you don't always want to delete, sometimes you want to copy or cut... as you go on to point out.

If one has to press 2 key combos in a sequence, one might as well press "home" or "end" key before starting selecting.
For copy or cut the desired behavior is already there, built-in, as I wrote.

But apparently you are joining a long line of "script whiners" [...]

I guess they decline because they are intimidated by scripts or don't trust them. And then either wait or pick another editor.

I'll personally take the script, but also wait for built-in: faster, cleaner editor overall.

@victorel-petrovich
Copy link
Author

victorel-petrovich commented Jul 25, 2023

Back to the script:
I don't fully understand what it does,
but for the purpose of just deleting the respective lines, won't it be more efficient not to expand the selection (with visible, thus time consuming side effects )
but instead to just find out the the position of start and end chars and delete all in between them, inclusive?

(I think same argument could be made for purpose of copy or cut functionality, if it didn't exist already).

@victorel-petrovich
Copy link
Author

That doesn't mean I don't find your script useful; I'm just a bit perfectionistic sometimes.

@alankilborn
Copy link
Contributor

If one has to press 2 key combos in a sequence, one might as well press "home" or "end" key before starting selecting.

So...modify the script as I suggested, to get all-in-one behavior.

For copy or cut the desired behavior is already there, built-in, as I wrote.

I don't understand this statement. How does one (natively) copy/cut on a whole-line basis, when the first and/or last line of a multiline selection is partial?

won't it be more efficient not to expand the selection (with visible, thus time consuming side effects ) but instead to just find out the the position of start and end chars and delete all in between them, inclusive?

Sure, but I made the script for my usage long ago, not for your specific need due to this thread. Modify the script as you see fit.

@alankilborn
Copy link
Contributor

For copy or cut the desired behavior is already there, built-in, as I wrote.

I don't understand this statement. How does one (natively) copy/cut on a whole-line basis, when the first and/or last line of a multiline selection is partial?

Ah, I'm catching on:

Just like you can already "copy" or "cut" lines in selection with a shortcut bound to "SCI_LINECOPY" and "SCI_LINECUT".

These commands do indeed operate on the full lines of a partial selection.

I'd say since that's the case, the lack of symmetry with SCI_LINEDELETE is a Scintilla bug (of omission).

You might want to file a report on the Scintilla site and see what the authors of that project respond with. https://www.scintilla.org

@victorel-petrovich
Copy link
Author

victorel-petrovich commented Jul 26, 2023

Found 2 other similar requests/wishes (many more outside Notepad++):
https://superuser.com/questions/258345/how-do-i-make-notepad-delete-lines-like-eclipse-does
https://community.notepad-plus-plus.org/topic/23096/improve-sci_linedelete-shortcut/4?_=1690356151820

In the first link, the best they came up with was recording macro of several operations (like: join-lines, HOME, shift+END, SCI_LINEDELETE), but that is not consistent with SCI_LINECOPY and SCI_LINECUT in all possible cases.

In second one, it's a shorter code by you; I installed, tested, and it is consistent with copy & cut.
Pasting it here for convenience:

# -*- coding: utf-8 -*-
#-------------------------------------------------------------------------------

class LD(object):

    def __init__(self):
        if editor.getSelections() > 1 and not editor.selectionIsRectangle(): return  # unsupported for now
        editor.beginUndoAction()
        if editor.getCurrentPos() != editor.getAnchor():
            (line_start, line_end) = editor.getUserLineSelection()
            if line_start != line_end:
                start_pos = editor.positionFromLine(line_start)
                end_pos = editor.getLineEndPosition(line_end)
                editor.deleteRange(start_pos, end_pos - start_pos)
        editor.lineDelete()
        editor.endUndoAction()

#-------------------------------------------------------------------------------

if __name__ == '__main__': LD()

@alankilborn
Copy link
Contributor

The "LD" (LineDelete) script is originally from HERE.

@alankilborn
Copy link
Contributor

I remembered why I prefer the selection to be a separate action from the delete/copy/cut.

That way I have only one additional thing to remember (a keycombo for the script that expands current selection to whole-lines). After invoking that, the standard Delete/Ctrl+c/Ctrl+x works for me. I don't have to remember 3 keycombos, one for each of the "enhanced" functionality.

@alankilborn
Copy link
Contributor

It's fine to keep discussing further points about this here, but I'm reasonably confident that Notepad++ itself will never make a code change to support what is wanted. IMO Scintilla should bring the behavior for SCI_LINEDELETE into alignment with how SCI_LINECOPY and SCI_LINECUT work.

@victorel-petrovich
Copy link
Author

I'm going to suggest it to Scintilla. But if they decline, then let N++ do it; hope dies last :) .

That way I have only one additional thing to remember (a keycombo for the script that expands current selection to whole-lines). After invoking that, the standard Delete/Ctrl+c/Ctrl+x works for me. I don't have to remember 3 keycombos, one for each of the "enhanced" functionality.

Try this: Shift+Delete/Shift+Ctrl+c/Shift+Ctrl+x , easier than: Ctrl+Alt+Shift+w then Delete/Ctrl+c/Ctrl+x.

@alankilborn
Copy link
Contributor

Try this: Shift+Delete/Shift+Ctrl+c/Shift+Ctrl+x , easier than: Ctrl+Alt+Shift+w then Delete/Ctrl+c/Ctrl+x

I already have those assigned. And I don't have mine assigned to Ctrl+Alt+Shift+w; that was just my suggestion to you because when I suggest such things to people, I don't suggest keycombos that N++ maps by default. To each his own. :-)

@alankilborn
Copy link
Contributor

I'm going to suggest it to Scintilla. But if they decline, then let N++ do it; hope dies last

Good luck.
Scintilla will probably decline at first -- seems to be their knee-jerk reaction to every suggestion. Then they typically warm up to things that make sense.

@victorel-petrovich
Copy link
Author

@victorel-petrovich
Copy link
Author

victorel-petrovich commented Aug 1, 2023

Neil replied: https://sourceforge.net/p/scintilla/feature-requests/1489/#48c8

I'll accept a good complete patch that implements this and includes a test case in test/simpleTests.py.

@alankilborn
Copy link
Contributor

@victorel-petrovich Are you going to work on such a patch?

@victorel-petrovich
Copy link
Author

victorel-petrovich commented Aug 4, 2023

@alankilborn I'd like to, I plan to; unless someone else does it before me.
Just don't know how hard it's going to be and how long will take.
My "milestones" would be:

  • script the solution in PythonScript (in a more low level, efficient way than the one known -- IF possible)
  • translate to NppExec script (to work w/ scintilla raw messages/commands)
  • translate to C or C++

EDIT:

  • if someone else does it earlier - I don't mind
  • if anyone wans to join or guide me - welcome !

@rdipardo
Copy link
Contributor

rdipardo commented Aug 4, 2023

My "milestones" would be:

  • script the solution in PythonScript (in a more low level, efficient way than the one known)
  • tranlate to NppExec script (to work w/ scintilla raw messages/commands)
  • translate to C or C++

I think you have it backwards. Plugins direct messages to a compiled Scintilla library at the heart of N++'s own compiled source code. What N++ does with the message depends on how N++ (or Scintilla) was programmed.

Your feature request would extend Scintilla's functionality. The most that PythonScript can do is test out the new functionality after it's been implemented — in C++.

Scintilla's code is hosted in a mercurial repository; you'll want to have the appropriate version control client installed first.

@victorel-petrovich
Copy link
Author

victorel-petrovich commented Aug 4, 2023

@rdipardo , correct me if I'm wrong:
The messages and constants documented at https://www.scintilla.org/ScintillaDoc.html are what one would use in order to code the solution in C++ . Or very close to them.
The messages used NppExec are closer to those above than functions (methods of editor object) in PythonScript.
The functions in PythonScript are wrappers around those messages, making the code feel more like a pseudocode.

So it's just easier (for me!) to start with PythonScript. To bridge the abstraction downwards. Makes sense?
Besides, I want to try scripting N++ too, along the way.

Your feature request would extend Scintilla's functionality.

I'm not that lost :)

Scintilla's code is hosted in a mercurial repository; you'll want to have the appropriate version control client installed first.

thanks

EDIT: perhaps this line of mine

script the solution in PythonScript (in a more low level, efficient way than the one known)

was confusing. I meant a different algorithm than the ones in this thread, at a more char-s level (thus "low level") .

@alankilborn
Copy link
Contributor

alankilborn commented Aug 4, 2023

How I would approach it:

  • Notepad++'s Scintilla is in source code form inside the Notepad++ project code, so I'd get that code and start working on an initial version of the fix there (because the Scintilla code is present in Notepad++, just loading the N++ project/solution into Visual Studio gives it all to you -- you're set to change code and single-step debug)

  • I'd look at how the "copy" and "cut" versions work, and then put very similar code into "delete" (I presume the Scintilla peeps would like to see a patch that is very much like similar existing code for other functionality)

  • When I've got it working, I'd then figure out how to package it in the way Scintilla peeps want it (not sure what that is as I've never looked into how they accept changes).

@victorel-petrovich
Copy link
Author

victorel-petrovich commented Aug 4, 2023

Thank you @alankilborn !
Step 1 seems brilliant, if you mean that when building N++ , Scintilla code also gets compiled ? I can't install Visual Studio on my Win7 32bit system (the BUILD.MD page says need Microsoft Visual Studio 2022), but Yesterday I just tried appveyor for building.
Thus I could test the function of the new SCI_LINEDELETE (based on my code) directly in N++ ?!

EDIT: this page seems to confirm that: https://github.com/notepad-plus-plus/notepad-plus-plus/blob/master/BUILD.md

Yes, I also figured that "cut" probably works by doing copy then delete, so I could take part of its code.

@alankilborn
Copy link
Contributor

when building N++ , Scintilla code also gets compiled ?

Yes.

I could test the function of the new SCI_LINEDELETE (based on my code) directly in N++ ?!

Again, yes.

@victorel-petrovich
Copy link
Author

It's fine to keep discussing further points about this here, but I'm reasonably confident that Notepad++ itself will never make a code change to support what is wanted. IMO Scintilla should bring the behavior for SCI_LINEDELETE into alignment with how SCI_LINECOPY and SCI_LINECUT work.

@victorel-petrovich victorel-petrovich closed this as not planned Won't fix, can't repro, duplicate, stale Aug 19, 2023
@alankilborn
Copy link
Contributor

You could have left this open, and if Scintilla implements it could be a "closed as completed" (at next Scintilla integration) and that way it might make the Notepad++ change log list when a N++ release supporting it is made.

@victorel-petrovich
Copy link
Author

victorel-petrovich commented Aug 24, 2023

Do you know where to find the code for SCI_LINEDELETE function?
I searched that word in the entire source code of Npp, no function definition itself.
image

EDIT:
Found this, it's probably it:

case Message::LineDelete: {

@victorel-petrovich
Copy link
Author

victorel-petrovich commented Aug 24, 2023

The change has indeed been trivial.
Here's the executable and code:

https://ci.appveyor.com/project/victorel-petrovich/notepad-plus-plus-vic/builds/47875550/artifacts

victorel-petrovich@0a289fb

@alankilborn
Copy link
Contributor

Ok, but that doesn't do anything to get Scintilla project to accept the code. Perhaps your plan it to submit the same thing on Scintilla, but then that begs the question, why submit the code here?

Just my feeling: You should probably avoid refactoring, unless you really know that is appreciated by the project owners.

@victorel-petrovich
Copy link
Author

victorel-petrovich commented Aug 24, 2023

@alankilborn
Copy link
Contributor

Do you know where to find the code for SCI_LINEDELETE function?
I searched that word in the entire source code of Npp, no function definition itself.

This would have been perfect to ask in the "new" Notepad++ Community area: https://community.notepad-plus-plus.org/category/5/notepad-plugin-development

But, since you asked here...

The "trick" to finding Scintilla functions is to search for them without the SCI_ on the front, and without regard to case.
Thus, SCI_LINEDELETE can be located by doing a Find in Files for linedelete.

Alternatively, if you DO search for SCI_LINEDELETE you will get a hit on #define SCI_LINEDELETE 2338
If you then search for 2338, you will get this hit: LineDelete = 2338
And finally, searching for LineDelete will get you where you originally wanted, which was:

	case Message::LineDelete: {
			const Sci::Line line = pdoc->SciLineFromPosition(sel.MainCaret());
			const Sci::Position start = pdoc->LineStart(line);
			const Sci::Position end = pdoc->LineStart(line + 1);
			pdoc->DeleteChars(start, end - start);
		}

@alankilborn
Copy link
Contributor

The "trick" to finding Scintilla functions is to...

The point of the above posting, even though you already found what you were looking for, is to keep the method in mind for next time you need to do something similar.

@Yaron10
Copy link

Yaron10 commented Nov 5, 2023

תמונה

- SCI_LINEDELETE deletes the current line only.
- SCI_LINECUT cuts the three lines.

The "current line" and the "selected lines" are two different "entities".
Most commands operating on entire-doc or selection-only exclude the "current line" in that case.

The current SCI_LINECUT behavior is contrary to Notepad++ concept.

  1. I'd expect "Cut Current Line" to ignore the selection and cut the current line only. - The user can use Cut to cut the selection.
  2. You can add a command - appropriately named - cutting the three lines.

And regardless of Notepad++:
Cutting the three lines is not the expected default result of "Cut Current Line".

@victorel-petrovich
Copy link
Author

The implemented behaviour of both SCI_LINECUT and SCI_LINECOPY is unlikely to be changed. And they behave by "lines touched by selection" - that is, including lines where either start or end marker of selection are located.
Bringing the delete one into alignment is a natural extension, that at least would result in less inconsistency.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants