Compare commits

...

6 Commits

Author SHA1 Message Date
Kim Woelders d213ac8887 eesh: Fix prompt when command has no reply 2023-12-23 15:36:32 +01:00
Kim Woelders 46f0a72ea4 eesh: Add possibility to use editline (--with-editline, default off) 2023-12-23 15:35:51 +01:00
Kim Woelders d659c3036a eesh: Add prompt if interactive 2023-12-23 09:26:10 +01:00
Kim Woelders 1bfc29c007 eesh: Move some code around 2023-12-23 09:26:10 +01:00
Kim Woelders 33d89e9b07 ipc: Ignore whitespace only command lines
Avoiding error dialog.
2023-12-23 09:25:54 +01:00
Kim Woelders d094c7d925 events: Drop select() based event loop
poll() is available everywhere, I think.
2023-12-22 04:28:30 +01:00
5 changed files with 120 additions and 128 deletions

View File

@ -62,23 +62,6 @@ if test "x$have_clock_gettime" != xno; then
fi
fi
AC_ARG_WITH(evhan,
AS_HELP_STRING([--with-evhan],
[select event handling api (poll/select)@<:@default=auto@:>@]),,
AC_CHECK_HEADERS(poll.h, with_evhan=poll, with_evhan=select))
case "$with_evhan" in
poll)
AC_CHECK_HEADERS(poll.h,, AC_MSG_ERROR([Need poll.h]))
AC_DEFINE(USE_EVHAN_POLL, 1, [Use poll as event handler api])
;;
select)
AC_DEFINE(USE_EVHAN_SELECT, 1, [Use select as event handler api])
;;
*)
AC_MSG_ERROR([Invalid option: --with-evhan=$with_evhan])
;;
esac
AC_ARG_ENABLE(sound,
AS_HELP_STRING([--enable-sound],
[compile with sound support (select default) (yes/no/pulseaudio/esound/sndio/alsa/player)@<:@default=yes@:>@]),
@ -401,6 +384,18 @@ if test "x$enable_dbus" = "xyes"; then
fi
AM_CONDITIONAL(ENABLE_DBUS, test "x$enable_dbus" = "xyes")
AC_ARG_WITH(lineedit,
AS_HELP_STRING([--with-lineedit], [compile eesh with line editing support (no/yes=editline/readline)@<:@default=no@:>@]),, with_lineedit="no")
if test "x$with_lineedit" = "xyes"; then
PKG_CHECK_MODULES(LINEEDIT, libeditline,
AC_DEFINE(USE_LINEEDIT_EDITLINE, 1, [Use editline])
with_lineedit="editline", with_lineedit="no")
elif test "x$with_lineedit" = "xreadline"; then
PKG_CHECK_MODULES(LINEEDIT, readline,
AC_DEFINE(USE_LINEEDIT_READLINE, 1, [Use readline])
with_lineedit="readline", with_lineedit="no")
fi
AC_CHECK_LIB(Fridge,mass_quantities_of_bass_ale)
AC_CHECK_LIB(Fridge,mass_quantities_of_any_ale,, [
echo "Warning: No ales were found in your refrigerator."
@ -565,9 +560,9 @@ echo " Window mode helper library ... $enable_libhack"
echo " Dialogs ...................... $enable_dialogs"
echo
echo "Miscellaneous options"
echo " Event handler API ............ $with_evhan"
echo " Use Modules .................. $enable_modules"
echo " Visibility hiding ............ $enable_visibility_hiding (only useful with modules)"
echo " Line editing (eesh) .......... $with_lineedit"
echo
echo "Experimental options - DO NOT USE unless you know what you are doing"
echo " GLX .......................... $enable_glx"

View File

@ -3,8 +3,8 @@ bin_PROGRAMS = eesh
AM_CPPFLAGS = -I$(top_builddir) $(X_CFLAGS)
AM_CFLAGS = $(CFLAGS_WARNINGS) $(CFLAGS_VISIBILITY) $(CFLAGS_ASAN)
AM_CFLAGS = $(CFLAGS_WARNINGS) $(CFLAGS_VISIBILITY) $(CFLAGS_ASAN) $(LINEEDIT_CFLAGS)
eesh_SOURCES = E.h comms.c main.c
eesh_LDADD = $(X_LIBS) -lX11
eesh_LDADD = $(X_LIBS) -lX11 $(LINEEDIT_LIBS)

View File

@ -22,6 +22,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -30,37 +31,52 @@
#include <X11/Xlib.h>
#include "E.h"
#if USE_LINEEDIT_EDITLINE
#define USE_LINEEDIT 1
#include <editline.h>
#elif USE_LINEEDIT_READLINE
#define USE_LINEEDIT 1
#include <readline/readline.h>
#include <readline/history.h>
#endif
#define PROMPT "eesh> "
Display *disp;
static char buf[10240];
static int nin; // Bytes in buffer
static Client *e;
static bool use_prompt;
static bool input_pending;
static bool reply_pending;
static void
process_line(char *line)
{
input_pending = false;
if (!line)
exit(0);
if (*line == '\0')
if (*line)
{
CommsSend(e, line);
XSync(disp, False);
reply_pending = true;
}
#if USE_LINEEDIT
if (!use_prompt)
return;
CommsSend(e, line);
XSync(disp, False);
}
static void
stdin_state_setup(void)
{
}
static void
stdin_state_restore(void)
{
rl_set_prompt("");
add_history(line);
#endif
}
static void
stdin_read(void)
{
static char buf[10240];
static int nin; // Bytes in buffer
int nr;
char *p;
@ -92,21 +108,33 @@ stdin_read(void)
}
}
#if USE_LINEEDIT
static void
stdin_state_setup(void)
{
rl_callback_handler_install("", process_line);
}
static void
stdin_state_restore(void)
{
rl_callback_handler_remove();
}
#endif
int
main(int argc, char **argv)
{
XEvent ev;
Window my_win, comms_win;
Client *me;
int i;
int rc, i;
struct pollfd pfd[2];
int nfd, timeout;
char *command, *s;
char mode;
int len, l;
const char *space;
mode = 0;
bool interactive;
for (i = 1; i < argc; i++)
{
@ -150,7 +178,6 @@ main(int argc, char **argv)
space = "";
if (i < argc)
{
mode = 1;
len = 0;
for (; i < argc; i++)
{
@ -167,21 +194,29 @@ main(int argc, char **argv)
}
}
input_pending = false;
reply_pending = false;
if (command)
{
/* Non-interactive */
interactive = use_prompt = false;
CommsSend(e, command);
XSync(disp, False);
#if 0 /* No - Wait for ack */
if (mode <= 0)
goto done;
#endif
reply_pending = true;
}
else
{
/* Interactive */
stdin_state_setup();
atexit(stdin_state_restore);
interactive = true;
use_prompt = isatty(STDIN_FILENO);
#if USE_LINEEDIT
if (use_prompt)
{
stdin_state_setup();
atexit(stdin_state_restore);
}
#endif
}
memset(pfd, 0, sizeof(pfd));
@ -190,7 +225,6 @@ main(int argc, char **argv)
pfd[1].fd = STDIN_FILENO;
pfd[1].events = POLLIN;
nfd = command ? 1 : 2;
timeout = -1;
for (;;)
{
@ -204,11 +238,14 @@ main(int argc, char **argv)
s = CommsGet(me, &ev);
if (!s)
break;
reply_pending = false;
if (*s)
{
printf("%s", s);
fflush(stdout);
fflush(stdout);
}
Efree(s);
if (mode)
if (!interactive)
goto done;
break;
case DestroyNotify:
@ -216,14 +253,40 @@ main(int argc, char **argv)
}
}
if (poll(pfd, nfd, timeout) < 0)
if (use_prompt && !input_pending && !reply_pending)
{
#if USE_LINEEDIT
rl_set_prompt(PROMPT);
rl_forced_update_display();
#else
printf(PROMPT);
fflush(stdout);
#endif
}
timeout = reply_pending ? 10 : -1;
rc = poll(pfd, nfd, timeout);
if (rc < 0)
break;
if (rc == 0)
{
reply_pending = false;
continue;
}
if (pfd[1].revents)
{
if (pfd[1].revents & POLLIN)
{
stdin_read();
input_pending = true;
#if USE_LINEEDIT
if (use_prompt)
rl_callback_read_char();
else
#endif
stdin_read();
}
if (pfd[1].revents & POLLHUP)
break;

View File

@ -23,11 +23,7 @@
*/
#include "config.h"
#if USE_EVHAN_POLL
#include <poll.h>
#elif USE_EVHAN_SELECT
#include <sys/select.h>
#endif
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@ -350,17 +346,12 @@ ExtVersion(int ext_ix)
typedef struct {
#if 0 /* Unused */
const char *name;
#endif
#if USE_EVHAN_SELECT
int fd;
#endif
void (*handler)(void);
} EventFdDesc;
static int nfds = 0;
#if USE_EVHAN_POLL
static struct pollfd *pfdl = NULL;
#endif
static EventFdDesc *pfds = NULL;
int
@ -371,12 +362,8 @@ EventFdRegister(int fd, EventFdHandler *handler)
efd = nfds++;
pfds = EREALLOC(EventFdDesc, pfds, nfds);
#if USE_EVHAN_POLL
pfdl = EREALLOC(struct pollfd, pfdl, nfds);
pfdl[efd].fd = fd;
#elif USE_EVHAN_SELECT
pfds[efd].fd = fd;
#endif
pfds[efd].handler = handler;
@ -386,12 +373,8 @@ EventFdRegister(int fd, EventFdHandler *handler)
void
EventFdUnregister(int efd)
{
#if USE_EVHAN_POLL
if (pfdl[efd].fd > 0)
pfdl[efd].fd = -pfdl[efd].fd;
#elif USE_EVHAN_SELECT
pfds[efd].fd = -1;
#endif
}
/*
@ -1128,11 +1111,6 @@ EventsMain(void)
static int evq_size = 0;
static int evq_fetch = 0;
static XEvent *evq_ptr = NULL;
#if USE_EVHAN_SELECT
fd_set fdset;
int fdsize, fd;
struct timeval tval;
#endif
unsigned int time1, time2;
int dtl, dt;
int count, pfetch;
@ -1192,7 +1170,6 @@ EventsMain(void)
else if (XPending(disp))
continue;
#if USE_EVHAN_POLL
for (i = 0; i < nfds; i++)
pfdl[i].events = (i == 0 && Mode.events.block) ? 0 : POLLIN;
@ -1217,53 +1194,6 @@ EventsMain(void)
pfds[i].handler();
}
}
#elif USE_EVHAN_SELECT
FD_ZERO(&fdset);
fdsize = -1;
for (i = 0; i < nfds; i++)
{
if (Mode.events.block && i == 0)
continue;
fd = pfds[i].fd;
if (fd < 0)
continue;
if (fdsize < fd)
fdsize = fd;
FD_SET(fd, &fdset);
}
fdsize++;
if (dt > 0.)
{
tval.tv_sec = (long)dt / 1000;
tval.tv_usec = ((long)dt - tval.tv_sec * 1000) * 1000;
count = select(fdsize, &fdset, NULL, NULL, &tval);
}
else
{
count = select(fdsize, &fdset, NULL, NULL, NULL);
}
if (EDebug(EDBUG_TYPE_EVENTS))
Eprintf("%s: count=%d xfd=%d:%d dtl=%.6lf dt=%.6lf\n", __func__,
count, pfds[0].fd, FD_ISSET(pfds[0].fd, &fdset),
dtl * 1e-3, dt * 1e-3);
if (count <= 0)
continue; /* Timeout (or error) */
/* Excluding X fd */
for (i = 1; i < nfds; i++)
{
fd = pfds[i].fd;
if ((fd >= 0) && (FD_ISSET(fd, &fdset)))
{
if (EDebug(EDBUG_TYPE_EVENTS) > 1)
Eprintf("Event fd %d\n", i);
pfds[i].handler();
}
}
#endif
}
}

View File

@ -1882,15 +1882,19 @@ IpcExec(const char *params)
if (EDebug(EDBUG_TYPE_IPC))
Eprintf("%s: '%s'\n", __func__, params);
cmd[0] = 0;
cmd[0] = '\0';
num = 0;
if (params)
sscanf(params, "%100s %n", cmd, &num);
prm = (num > 0 && params[num]) ? params + num : NULL;
ok = 1;
if (cmd[0] == '\0')
goto done; /* Accept empty input */
lst = IPC_GetList(&num);
ok = 0;
for (i = 0; i < num; i++)
{
ipc = lst[i];
@ -1899,16 +1903,16 @@ IpcExec(const char *params)
ipc->func(prm);
ok = 1;
break;
goto done;
}
if (!ok && params)
ok = IPC_Compat(params);
/* Commmand not found - check the legacy ones */
ok = IPC_Compat(params);
if (!ok)
IpcPrintf("Unknown command: '%s'\n", params);
done:
return ok;
}