Compare commits

..

20 Commits
4.3 ... 4.4

Author SHA1 Message Date
bae58f61cf add lsx.1 to dist 2011-07-19 21:30:09 +01:00
1636e12210 tweaks 2011-07-17 14:06:53 +01:00
2b92c95230 efficiency tweaks 2011-07-14 20:03:08 +01:00
16a0c0d52a fix extra warning 2011-07-14 20:03:00 +01:00
5867c53390 simpler vline 2011-07-06 13:40:36 +01:00
34a816f87d rebind ^N ^P 2011-07-04 16:55:09 +01:00
0288b576ca include limits.h 2011-06-25 17:02:14 +01:00
59dafc4ad6 make clean lsx 2011-06-23 22:39:20 +01:00
49672e9d05 merge lsx -> default 2011-06-23 20:27:28 +01:00
07d452e0c8 close lsx branch 2011-06-23 20:26:57 +01:00
88d44169e9 lsx: check snprintf 2011-06-23 20:04:50 +01:00
f7cbe710a2 update draw.c 2011-06-18 22:11:19 +01:00
86e9e6f1ec simpler lsx 2011-06-18 07:50:46 +01:00
eadf090413 new dmenu_run 2011-06-13 21:50:31 +01:00
8ec1b41cac add lsx.1 2011-06-13 19:32:45 +01:00
ab3bcac0bf new lsx branch 2011-06-13 19:28:30 +01:00
723cbabc12 add ^M 2011-06-13 19:25:40 +01:00
86775cc44b Added tag 4.3.1 for changeset 34a2d77049a9 2011-05-18 17:01:59 +01:00
2103ae2891 bugfix 2011-05-18 17:01:44 +01:00
b028ec0e07 Added tag 4.3 for changeset 14c79f054bdf 2011-05-18 16:21:45 +01:00
11 changed files with 143 additions and 107 deletions

View File

@ -44,3 +44,5 @@ e4c81a78ffbad6ba4d1ad119cc654da6eca63a4c 3.2
72749a826cab0baa805620e44a22e54486c97a4e 4.1.1
379813a051f03a1b20bdbfdc2d2d1d2d794ace48 4.2
abb6579a324fffdf6a23c2fa4c32911277da594a 4.2.1
14c79f054bdf43ff3213af8e60a783192e92a018 4.3
34a2d77049a95b02f3332a0b88f9370965ebcfad 4.3.1

View File

@ -3,10 +3,10 @@
include config.mk
SRC = dmenu.c draw.c
SRC = dmenu.c draw.c lsx.c
OBJ = ${SRC:.c=.o}
all: options dmenu
all: options dmenu lsx
options:
@echo dmenu build options:
@ -20,18 +20,22 @@ options:
${OBJ}: config.mk
dmenu: ${OBJ}
dmenu: dmenu.o draw.o
@echo CC -o $@
@${CC} -o $@ ${OBJ} ${LDFLAGS}
@${CC} -o $@ dmenu.o draw.o ${LDFLAGS}
lsx: lsx.o
@echo CC -o $@
@${CC} -o $@ lsx.o ${LDFLAGS}
clean:
@echo cleaning
@rm -f dmenu ${OBJ} dmenu-${VERSION}.tar.gz
@rm -f dmenu lsx ${OBJ} dmenu-${VERSION}.tar.gz
dist: clean
@echo creating dist tarball
@mkdir -p dmenu-${VERSION}
@cp LICENSE Makefile README config.mk dmenu.1 draw.h dmenu_path dmenu_run ${SRC} dmenu-${VERSION}
@cp LICENSE Makefile README config.mk dmenu.1 draw.h dmenu_run lsx.1 ${SRC} dmenu-${VERSION}
@tar -cf dmenu-${VERSION}.tar dmenu-${VERSION}
@gzip dmenu-${VERSION}.tar
@rm -rf dmenu-${VERSION}
@ -39,21 +43,24 @@ dist: clean
install: all
@echo installing executables to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin
@cp -f dmenu dmenu_path dmenu_run ${DESTDIR}${PREFIX}/bin
@cp -f dmenu dmenu_run lsx ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu_path
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu_run
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
@chmod 755 ${DESTDIR}${PREFIX}/bin/lsx
@echo installing manual pages to ${DESTDIR}${MANPREFIX}/man1
@mkdir -p ${DESTDIR}${MANPREFIX}/man1
@sed "s/VERSION/${VERSION}/g" < dmenu.1 > ${DESTDIR}${MANPREFIX}/man1/dmenu.1
@sed "s/VERSION/${VERSION}/g" < lsx.1 > ${DESTDIR}${MANPREFIX}/man1/lsx.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dmenu.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/lsx.1
uninstall:
@echo removing executables from ${DESTDIR}${PREFIX}/bin
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu_path
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu_run
@rm -f ${DESTDIR}${PREFIX}/bin/lsx
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/dmenu.1
@rm -f ${DESTDIR}${MANPREFIX}/man1/lsx.1
.PHONY: all options clean dist install uninstall

View File

@ -1,5 +1,5 @@
# dmenu version
VERSION = 4.3
VERSION = 4.4
# paths
PREFIX = /usr/local

12
dmenu.1
View File

@ -23,12 +23,10 @@ dmenu \- dynamic menu
.RB [ \-v ]
.P
.BR dmenu_run " ..."
.P
.B dmenu_path
.SH DESCRIPTION
.B dmenu
is a dynamic menu for X, originally designed for
.BR dwm (1).
.IR dwm (1).
It manages huge numbers of user\-defined menu items efficiently.
.P
dmenu reads a list of newline\-separated items from stdin and creates a menu.
@ -36,11 +34,8 @@ When the user selects an item or enters any text and presses Return, their
choice is printed to stdout and dmenu terminates.
.P
.B dmenu_run
is a dmenu script used by dwm which lists programs in the user's PATH and
is a dmenu script used by dwm which lists programs in the user's $PATH and
executes the selected item.
.P
.B dmenu_path
is a script used by dmenu_run to find and cache a list of executables.
.SH OPTIONS
.TP
.B \-b
@ -100,4 +95,5 @@ Exit without selecting an item, returning failure.
.B Ctrl\-y
Paste the current X selection into the input field.
.SH SEE ALSO
.BR dwm (1)
.IR dwm (1),
.IR lsx (1)

106
dmenu.c
View File

@ -25,8 +25,8 @@ struct Item {
static void appenditem(Item *item, Item **list, Item **last);
static void calcoffsets(void);
static char *cistrstr(const char *s, const char *sub);
static void drawmenu(void);
static char *fstrstr(const char *s, const char *sub);
static void grabkeyboard(void);
static void insert(const char *str, ssize_t n);
static void keypress(XKeyEvent *ev);
@ -60,6 +60,7 @@ static Item *prev, *curr, *next, *sel;
static Window win;
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
static char *(*fstrstr)(const char *, const char *) = strstr;
int
main(int argc, char *argv[]) {
@ -76,8 +77,10 @@ main(int argc, char *argv[]) {
topbar = False;
else if(!strcmp(argv[i], "-f"))
fast = True;
else if(!strcmp(argv[i], "-i"))
else if(!strcmp(argv[i], "-i")) {
fstrncmp = strncasecmp;
fstrstr = cistrstr;
}
else if(i+1 == argc)
usage();
/* double flags */
@ -112,7 +115,7 @@ main(int argc, char *argv[]) {
setup();
run();
return EXIT_FAILURE; /* should not reach */
return EXIT_FAILURE; /* unreachable */
}
void
@ -121,6 +124,7 @@ appenditem(Item *item, Item **list, Item **last) {
*list = item;
else
(*last)->right = item;
item->left = *last;
item->right = NULL;
*last = item;
@ -143,6 +147,16 @@ calcoffsets(void) {
break;
}
char *
cistrstr(const char *s, const char *sub) {
size_t len;
for(len = strlen(sub); *s; s++)
if(!strncasecmp(s, sub, len))
return (char *)s;
return NULL;
}
void
drawmenu(void) {
int curpos;
@ -188,16 +202,6 @@ drawmenu(void) {
mapdc(dc, win, mw, mh);
}
char *
fstrstr(const char *s, const char *sub) {
size_t len;
for(len = strlen(sub); *s; s++)
if(!fstrncmp(s, sub, len))
return (char *)s;
return NULL;
}
void
grabkeyboard(void) {
int i;
@ -219,7 +223,7 @@ insert(const char *str, ssize_t n) {
if(n > 0)
memcpy(&text[cursor], str, n);
cursor += n;
match(n > 0);
match(n > 0 && text[cursor] == '\0');
}
void
@ -233,57 +237,37 @@ keypress(XKeyEvent *ev) {
XConvertCase(ksym, &lower, &upper);
switch(lower) {
default:
return;
case XK_a:
ksym = XK_Home;
break;
case XK_b:
ksym = XK_Left;
break;
case XK_c:
ksym = XK_Escape;
break;
case XK_d:
ksym = XK_Delete;
break;
case XK_e:
ksym = XK_End;
break;
case XK_f:
ksym = XK_Right;
break;
case XK_h:
ksym = XK_BackSpace;
break;
case XK_i:
ksym = XK_Tab;
break;
case XK_j:
ksym = XK_Return;
break;
case XK_k: /* delete right */
case XK_a: ksym = XK_Home; break;
case XK_b: ksym = XK_Left; break;
case XK_c: ksym = XK_Escape; break;
case XK_d: ksym = XK_Delete; break;
case XK_e: ksym = XK_End; break;
case XK_f: ksym = XK_Right; break;
case XK_h: ksym = XK_BackSpace; break;
case XK_i: ksym = XK_Tab; break;
case XK_j: ksym = XK_Return; break;
case XK_m: ksym = XK_Return; break;
case XK_n: ksym = XK_Up; break;
case XK_p: ksym = XK_Down; break;
case XK_k: /* delete right */
text[cursor] = '\0';
match(False);
break;
case XK_n:
ksym = XK_Down;
break;
case XK_p:
ksym = XK_Up;
break;
case XK_u: /* delete left */
case XK_u: /* delete left */
insert(NULL, 0 - cursor);
break;
case XK_w: /* delete word */
case XK_w: /* delete word */
while(cursor > 0 && text[nextrune(-1)] == ' ')
insert(NULL, nextrune(-1) - cursor);
while(cursor > 0 && text[nextrune(-1)] != ' ')
insert(NULL, nextrune(-1) - cursor);
break;
case XK_y: /* paste selection */
case XK_y: /* paste selection */
XConvertSelection(dc->dpy, XA_PRIMARY, utf8, utf8, win, CurrentTime);
return;
default:
return;
}
}
switch(ksym) {
@ -295,9 +279,11 @@ keypress(XKeyEvent *ev) {
if(text[cursor] == '\0')
return;
cursor = nextrune(+1);
/* fallthrough */
case XK_BackSpace:
if(cursor > 0)
insert(NULL, nextrune(-1) - cursor);
if(cursor == 0)
return;
insert(NULL, nextrune(-1) - cursor);
break;
case XK_End:
if(text[cursor] != '\0') {
@ -329,8 +315,7 @@ keypress(XKeyEvent *ev) {
cursor = nextrune(-1);
break;
}
else if(lines > 0)
return;
/* fallthrough */
case XK_Up:
if(sel && sel->left && (sel = sel->left)->right == curr) {
curr = prev;
@ -351,15 +336,14 @@ keypress(XKeyEvent *ev) {
break;
case XK_Return:
case XK_KP_Enter:
fputs((sel && !(ev->state & ShiftMask)) ? sel->text : text, stdout);
puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
exit(EXIT_SUCCESS);
case XK_Right:
if(text[cursor] != '\0') {
cursor = nextrune(+1);
break;
}
else if(lines > 0)
return;
/* fallthrough */
case XK_Down:
if(sel && sel->right && (sel = sel->right) == next) {
curr = next;
@ -469,7 +453,7 @@ run(void) {
switch(ev.type) {
case Expose:
if(ev.xexpose.count == 0)
drawmenu();
mapdc(dc, win, mw, mh);
break;
case KeyPress:
keypress(&ev.xkey);

View File

@ -1,9 +0,0 @@
#!/bin/sh
CACHE=$HOME/.dmenu_cache
IFS=:
if ! test -f "$CACHE" || find $PATH -type d -newer "$CACHE" | grep -q .; then
find $PATH ! -type d \( -perm -1 -o -perm -10 -o -perm -100 \) | sed 's/.*\///' | sort -u > "$CACHE"
fi
cat "$CACHE"

View File

@ -1,2 +1,9 @@
#!/bin/sh
exe=`dmenu_path | dmenu ${1+"$@"}` && exec $exe
CACHE=${XDG_CACHE_HOME:-"$HOME/.cache"}/dmenu_run
(
IFS=:
if test "`ls -dt $PATH "$CACHE" 2> /dev/null | sed 1q`" != "$CACHE"; then
mkdir -p "`dirname "$CACHE"`" && lsx $PATH | sort -u > "$CACHE"
fi
)
cmd=`dmenu "$@" < "$CACHE"` && exec $cmd

33
draw.c
View File

@ -96,7 +96,7 @@ initdc(void) {
DC *dc;
if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fprintf(stderr, "no locale support\n");
fputs("no locale support\n", stderr);
if(!(dc = calloc(1, sizeof *dc)))
eprintf("cannot malloc %u bytes:", sizeof *dc);
if(!(dc->dpy = XOpenDisplay(NULL)))
@ -120,24 +120,23 @@ initfont(DC *dc, const char *fontstr) {
Bool
loadfont(DC *dc, const char *fontstr) {
char *def, **missing;
int i, n;
char *def, **missing, **names;
int i, n = 1;
XFontStruct **xfonts;
if(!*fontstr)
return False;
if((dc->font.set = XCreateFontSet(dc->dpy, fontstr, &missing, &n, &def))) {
char **names;
XFontStruct **xfonts;
if((dc->font.set = XCreateFontSet(dc->dpy, fontstr, &missing, &n, &def)))
n = XFontsOfFontSet(dc->font.set, &xfonts, &names);
for(i = dc->font.ascent = dc->font.descent = 0; i < n; i++) {
dc->font.ascent = MAX(dc->font.ascent, xfonts[i]->ascent);
dc->font.descent = MAX(dc->font.descent, xfonts[i]->descent);
}
}
else if((dc->font.xfont = XLoadQueryFont(dc->dpy, fontstr))) {
dc->font.ascent = dc->font.xfont->ascent;
dc->font.descent = dc->font.xfont->descent;
else if((dc->font.xfont = XLoadQueryFont(dc->dpy, fontstr)))
xfonts = &dc->font.xfont;
else
n = 0;
for(i = 0; i < n; i++) {
dc->font.ascent = MAX(dc->font.ascent, xfonts[i]->ascent);
dc->font.descent = MAX(dc->font.descent, xfonts[i]->descent);
dc->font.width = MAX(dc->font.width, xfonts[i]->max_bounds.width);
}
if(missing)
XFreeStringList(missing);
@ -154,10 +153,10 @@ resizedc(DC *dc, unsigned int w, unsigned int h) {
if(dc->canvas)
XFreePixmap(dc->dpy, dc->canvas);
dc->canvas = XCreatePixmap(dc->dpy, DefaultRootWindow(dc->dpy), w, h,
DefaultDepth(dc->dpy, DefaultScreen(dc->dpy)));
dc->w = w;
dc->h = h;
dc->canvas = XCreatePixmap(dc->dpy, DefaultRootWindow(dc->dpy), w, h,
DefaultDepth(dc->dpy, DefaultScreen(dc->dpy)));
}
int

1
draw.h
View File

@ -15,6 +15,7 @@ typedef struct {
int ascent;
int descent;
int height;
int width;
XFontSet set;
XFontStruct *xfont;
} font;

11
lsx.1 Normal file
View File

@ -0,0 +1,11 @@
.TH LSX 1 dmenu\-VERSION
.SH NAME
lsx \- list executables
.SH SYNOPSIS
.B lsx
.RI [ directory ...]
.SH DESCRIPTION
.B lsx
lists the executables in each
.IR directory .
If none are given the current working directory is used.

38
lsx.c Normal file
View File

@ -0,0 +1,38 @@
/* See LICENSE file for copyright and license details. */
#include <dirent.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
static void lsx(const char *dir);
int
main(int argc, char *argv[]) {
int i;
if(argc < 2)
lsx(".");
else for(i = 1; i < argc; i++)
lsx(argv[i]);
return EXIT_SUCCESS;
}
void
lsx(const char *dir) {
char buf[PATH_MAX];
struct dirent *d;
struct stat st;
DIR *dp;
if(!(dp = opendir(dir))) {
perror(dir);
return;
}
while((d = readdir(dp)))
if(snprintf(buf, sizeof buf, "%s/%s", dir, d->d_name) < (int)sizeof buf
&& !stat(buf, &st) && S_ISREG(st.st_mode) && access(buf, X_OK) == 0)
puts(d->d_name);
closedir(dp);
}