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

Menu (feature request) #438

Closed
marco-trovato opened this issue Aug 8, 2023 · 8 comments
Closed

Menu (feature request) #438

marco-trovato opened this issue Aug 8, 2023 · 8 comments

Comments

@marco-trovato
Copy link

This is currently the only text editor for terminal with CUA standard keybindings that supports text selection, mouse, and ESPECIALLY text folding/collapsing (it's literally the only one with this feature).

Tilde, Micro, and NiceEditor are missing these features.

Can you please...please🙏 add a menu? Even just with File -> Open / Save / Quit
Thank you

@orbitalquark
Copy link
Owner

orbitalquark commented Aug 9, 2023

I agree this would be nice to have. Thanks for the reminder. While CDK (the terminal widget toolkit Textadept uses) supports menu widgets, I don't think it has a menu bar or support for nested submenus. Writing those widgets would be difficult for me, so that's why the terminal version of Textadept doesn't have menus :(

The "Tools > Select Command" (Ctrl+P) dialog helps alleviate this to an extent though.

@marco-trovato
Copy link
Author

marco-trovato commented Aug 11, 2023

Honest question: is it really that difficult to

  1. Without even saving the text buffer currently on the screen, just violently print withut grace on the top of the screen "FILE" with "SAVE, LOAD and QUIT" below
  2. Wait for the right hotkey and call the relative function
  3. Just redraw/refresh the screen to show the editor to return to the working file

?

I ask because it sounds like 10 lines of C code to my experience and it would make a huge difference in term of usability and initial learning curve.

(instead of hardcoding the menu it could be even easily possibile to use an external file which binds a new item of the menu to the relative function)

@orbitalquark
Copy link
Owner

It might not be difficult to do, but it is a hard-coded, half-baked, inflexible solution that defeats the purpose of Textadept. Using an external file adds an additional layer of complexity (and failure point) that would likely not be worth it.

Ctrl+P for now is the way to go through Textadept's menu in the terminal.

@marco-trovato
Copy link
Author

marco-trovato commented Aug 12, 2023

You are 100% right I didn't know about CTRL-P.
I have only one simple legit question: why in the holy cult of the dead cow did you chose CTRL-P instead of ESC ? This menu would have been perfect if I only knew it existed

@orbitalquark
Copy link
Owner

orbitalquark commented Aug 12, 2023 via email

@oOosys
Copy link

oOosys commented Oct 5, 2024

Why isn't this issue closed yet?

@orbitalquark
Copy link
Owner

I need to find the time to experiment with https://invisible-mirror.net/cdk/manpage/cdk_menu.3.html and see if it's viable. If it's not, then I'll close this.

@orbitalquark
Copy link
Owner

After investigating further, CDK's menu widget is too limited.

  • It does not support more than one level of sub-menus
    • It might be possible to construct a top-level menu in such a way that the submenu's title is used as a label, and if that menu item is selected, activate a new menu with the sub-menu. However, mapping activateCDKMenu()'s return value to a submenu to show next is not trivial, nor is mapping a sub-menu's return value to a menu ID. That last bit is probably a dealbreaker.
  • It does not appear to support menu separators
  • read_menu() cannot return a newCDKMenu(), but probably has to return a list of labels or some sort of malloc()ed struct; it WILL leak memory, as there is no way to free it after the fact

For reference, here is my test snippet:

void *read_menu(lua_State *L, int index) {
	const char **menu = calloc(lua_rawlen(L, index) + 1, sizeof(const char *));
	for (size_t i = 1; i <= lua_rawlen(L, index); lua_pop(L, 1), i++) {
		if (lua_rawgeti(L, index, i) != LUA_TTABLE) continue; // popped on loop
		bool is_submenu = lua_getfield(L, -1, "title");
		if (!is_submenu) lua_rawgeti(L, -2, 1), lua_replace(L, -2);
		const char *label = lua_tostring(L, -1);
		if (label && !*label) label = "---";
		if (label) menu[i - 1] = strcpy(malloc(strlen(label)), label);
		lua_pop(L, 1); // label
	}
	return menu;
}

void popup_menu(void *menu, void *userdata) {
	const char **labels = menu;
	int n = 0, width = 0;
	for (n = 1; labels[n]; n++) width = fmax(width, strlen(labels[n]));
	int location[n];
	for (int i = 0; i < n; i++) location[i] = LEFT;
	CDKSCREEN *screen = initCDKScreen(newwin(n + 2, width + 2, 1, 1));
	const char *m[1][n];
	for (int i = 0; i < n; i++) m[0][i] = labels[i];
	CDKMENU *cdk_menu = newCDKMenu(screen, m, 1, &n, location, TOP, A_NORMAL, A_REVERSE);
	activateCDKMenu(cdk_menu, NULL);
	destroyCDKMenu(cdk_menu), delwin(screen->window), destroyCDKScreen(screen);
}

I also had to update CMakeLists.txt to include menu.c.

Using that snippet I was able to run popup_menu(ui.context_menu) from the command entry to show the menu. Selecting a label does not do anything.

Closing this. The workaround for lack of a menu is Ctrl+P.

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

3 participants