kb shortcut: tab indent selection (Shift Left/Right)
Brought to you by:
tringali
I have created a patch for Nedit 5.6 that changes the "Shift Left/Right" tab indentation keyboard shortcuts from Ctrl-Shift-9/Ctrl-Shift-0 to Shift Tab/Tab respectively. This makes the [Shift] Tab key indent selected text when text is selected (rather than simply inserting a tab character). These keyboard shortcuts are commonly used in modern text editors (e.g. TextPad/MS Visual Studio/etc).
Here is a summary of the changes;
nedit.h;
~l45:
#define TAB_SELECT_SHIFT_TEXT_PATCH
nedit.c;
~l266:
#ifdef TAB_SELECT_SHIFT_TEXT_PATCH
"*editMenu.shiftLeft.accelerator: Ctrl<Key>9",
"*editMenu.shiftLeft.acceleratorText: Shift Tab",
"*editMenu.shiftLeftShift.accelerator: Shift<Key>Tab",
"*editMenu.shiftRight.accelerator: Ctrl<Key>0",
"*editMenu.shiftRight.acceleratorText: Tab",
"*editMenu.shiftRightShift.accelerator: <Key>Tab",
#else
"*editMenu.shiftLeft.accelerator: Ctrl<Key>9",
"*editMenu.shiftLeft.acceleratorText: [Shift]Ctrl+9",
"*editMenu.shiftLeftShift.accelerator: Shift Ctrl<Key>9",
"*editMenu.shiftRight.accelerator: Ctrl<Key>0",
"*editMenu.shiftRight.acceleratorText: [Shift]Ctrl+0",
"*editMenu.shiftRightShift.accelerator: Shift Ctrl<Key>0",
#endif
menu.c;
~l107;
#ifdef TAB_SELECT_SHIFT_TEXT_PATCH
static void shiftLeftShiftCB(Widget w, XtPointer clientData, XtPointer callData);
static void shiftRightShiftCB(Widget w, XtPointer clientData, XtPointer callData);
#endif
~l741;
#ifdef TAB_SELECT_SHIFT_TEXT_PATCH
createFakeMenuItem(menuPane, "shiftLeftShift", shiftLeftShiftCB, window);
#else
createFakeMenuItem(menuPane, "shiftLeftShift", shiftLeftCB, window);
#endif
...
#ifdef TAB_SELECT_SHIFT_TEXT_PATCH
createFakeMenuItem(menuPane, "shiftRightShift", shiftRightShiftCB, window);
#else
createFakeMenuItem(menuPane, "shiftRightShift", shiftRightCB, window);
#endif
~1413;
#ifdef TAB_SELECT_SHIFT_TEXT_PATCH
static void shiftLeftShiftCB(Widget w, XtPointer clientData, XtPointer callData)
{
HidePointerOnKeyedEvent(WidgetToWindow(MENU_WIDGET(w))->lastFocus,
((XmAnyCallbackStruct *)callData)->event);
XtCallActionProc(WidgetToWindow(MENU_WIDGET(w))->lastFocus,
"shift_left_by_tab",
((XmAnyCallbackStruct *)callData)->event, NULL, 0);
}
static void shiftRightShiftCB(Widget w, XtPointer clientData, XtPointer callData)
{
WindowInfo *window = WidgetToWindow(MENU_WIDGET(w));
if(window->buffer->primary.selected)
{
HidePointerOnKeyedEvent(WidgetToWindow(MENU_WIDGET(w))->lastFocus,
((XmAnyCallbackStruct *)callData)->event);
XtCallActionProc(WidgetToWindow(MENU_WIDGET(w))->lastFocus,
"shift_right_by_tab",
((XmAnyCallbackStruct *)callData)->event, NULL, 0);
}
else
{
/*just add the 'tab' character as normal*/
XEvent *event = ((XmAnyCallbackStruct *)callData)->event;
/*
tw->text.autoWrapPastedText
*/
Widget tw = window->textArea;
TextInsertAtCursor(tw, "\t", event, True, True);
}
}
#endif
I like this. Will try it out. BTW, what's the reason for those "#ifdef TAB_SELECT_SHIFT_TEXT_PATCH"? Not sure why they are needed.
Hi TK Soh. The preprocessor defs are added for development purposes only (the patch is under testing). I have been testing this patch for 6 months now, and have detected these issues;
Thanks for the detail summary. Given the issues you experienced, with respect, I took a different approach by overloading the action procedure of tab key with a wrapper that calls "shift_right_by_tab" (or "shift_left_by_tab", on shift-tab) when user selected one line or more, or else call "process_tab" as done originally. I have compared it to notepad++ and it behaves similarly.
My hope is that this will maintain the backward compatibility to the original behavior, and let nedit handle the tab emulation accordingly too.
I've attached patch against the latest rev of nedit source. Please give it a try if you can. Let me know if you have any comment/concerns.
Cheers TK Soh - I have started to test the patch. Some issues I have noticed with this version;
Hi Richard. Thanks for testing and spotting the issue. Before we move further, perhaps we should first define the behavior of tab & shift-tab more clearly. I start by looking at the Qt Creator 4.12.2, Visual Studio 2019 v16.6.1 and Notepad++ on how they handle tab & shift-tab.
On Tab:
On Shift-Tab:
Personally I feel Qt and VS is more consistent and intuitive. Please share your thought. Thanks.
Last edit: TK Soh 2020-07-23
Thank you for performing this detailed experiment. I have added my preferred behaviour below, although the chosen "select part of line" behaviour is somewhat unique and is disputable as a reasonable development target.
Visual Studio 2017;
select multiple lines:
select whole of line;
select part of line;
position cursor:
Textpad 4;
select multiple lines:
select whole of line;
select part of line;
position cursor:
Qt Creator;
select multiple lines:
select whole of line;
select part of line;
position cursor:
Notepad++;
select multiple lines:
select whole of line;
select part of line;
position cursor:
RB patch #1 (nedit5.6UB-withSelectTab.patch);
select multiple lines:
select whole of line;
select part of line;
position cursor:
TK Soh patch #1 (nedit-tab-indent-tksoh-08072020.diff);
select multiple lines:
select whole of line;
select part of line;
cursor:
RB preferred (theoretical);
select multiple lines:
select whole of line;
select part of line;
position cursor:
Last edit: BAI Research 2020-07-24
My apology on the long silence, as I have been busy on the other projects that pay the bills.
Thanks for putting this very nice analysis together. Truth to be told, I am having a slight second thought on this feature, especially to this legacy NEdit (maybe the nedit-ng team can take on it instead). The good news is that NEdit already is able to achieve the purpose, just not what the users are used to when coming from using other more 'modern' editors. Perhaps it can wait a little.
Hi TK Soh, thanks for your analysis.
I recommend implementing your version (TK#1; nedit-tab-indent-tksoh-08072020.diff); it provides the core patch functionality with minimum behavioural changes to the original.
Patch against 5.7 release.