File: [local] / src / usr.bin / mg / grep.c (download)
Revision 1.38, Thu Jun 4 23:39:37 2009 UTC (15 years ago) by kjell
Branch: MAIN
CVS Tags: OPENBSD_5_3_BASE, OPENBSD_5_3, OPENBSD_5_2_BASE, OPENBSD_5_2, OPENBSD_5_1_BASE, OPENBSD_5_1, OPENBSD_5_0_BASE, OPENBSD_5_0, OPENBSD_4_9_BASE, OPENBSD_4_9, OPENBSD_4_8_BASE, OPENBSD_4_8, OPENBSD_4_7_BASE, OPENBSD_4_7, OPENBSD_4_6_BASE, OPENBSD_4_6 Changes since 1.37: +6 -6 lines
Add the notion of an "ephemeral" popup, so we can flag a window
for destruction at a later date. (in the process, add a window flag field)
This fixes an issue noted by maja: namely, the *completion*
window that pops up when you try to complete a filename on
buffer load would destroy any second window that you happened
to have open.
ok maja@
|
/* $OpenBSD: grep.c,v 1.38 2009/06/04 23:39:37 kjell Exp $ */
/* This file is in the public domain */
#include "def.h"
#include "kbd.h"
#include "funmap.h"
#include <sys/types.h>
#include <ctype.h>
#include <libgen.h>
#include <time.h>
int globalwd = FALSE;
static int compile_goto_error(int, int);
int next_error(int, int);
static int grep(int, int);
static int gid(int, int);
static struct buffer *compile_mode(const char *, const char *);
static int xlint(int, int);
void grep_init(void);
static char compile_last_command[NFILEN] = "make ";
/*
* Hints for next-error
*
* XXX - need some kind of callback to find out when those get killed.
*/
struct mgwin *compile_win;
struct buffer *compile_buffer;
static PF compile_pf[] = {
compile_goto_error
};
static struct KEYMAPE (1 + IMAPEXT) compilemap = {
1,
1 + IMAPEXT,
rescan,
{
{ CCHR('M'), CCHR('M'), compile_pf, NULL }
}
};
void
grep_init(void)
{
funmap_add(compile_goto_error, "compile-goto-error");
funmap_add(next_error, "next-error");
funmap_add(grep, "grep");
funmap_add(xlint, "lint");
funmap_add(compile, "compile");
funmap_add(gid, "gid");
maps_add((KEYMAP *)&compilemap, "compile");
}
/* ARGSUSED */
static int
grep(int f, int n)
{
char cprompt[NFILEN], *bufp;
struct buffer *bp;
struct mgwin *wp;
(void)strlcpy(cprompt, "grep -n ", sizeof(cprompt));
if ((bufp = eread("Run grep: ", cprompt, NFILEN,
EFDEF | EFNEW | EFCR)) == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
if (strlcat(cprompt, " /dev/null", sizeof(cprompt)) >= sizeof(cprompt))
return (FALSE);
if ((bp = compile_mode("*grep*", cprompt)) == NULL)
return (FALSE);
if ((wp = popbuf(bp, WNONE)) == NULL)
return (FALSE);
curbp = bp;
compile_win = curwp = wp;
return (TRUE);
}
/* ARGSUSED */
static int
xlint(int f, int n)
{
char cprompt[NFILEN], *bufp;
struct buffer *bp;
struct mgwin *wp;
(void)strlcpy(cprompt, "make lint ", sizeof(cprompt));
if ((bufp = eread("Run lint: ", cprompt, NFILEN,
EFDEF | EFNEW | EFCR)) == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
if ((bp = compile_mode("*lint*", cprompt)) == NULL)
return (FALSE);
if ((wp = popbuf(bp, WNONE)) == NULL)
return (FALSE);
curbp = bp;
compile_win = curwp = wp;
return (TRUE);
}
/* ARGSUSED */
int
compile(int f, int n)
{
char cprompt[NFILEN], *bufp;
struct buffer *bp;
struct mgwin *wp;
(void)strlcpy(cprompt, compile_last_command, sizeof(cprompt));
if ((bufp = eread("Compile command: ", cprompt, NFILEN,
EFDEF | EFNEW | EFCR)) == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
if (savebuffers(f, n) == ABORT)
return (ABORT);
(void)strlcpy(compile_last_command, bufp, sizeof(compile_last_command));
if ((bp = compile_mode("*compile*", cprompt)) == NULL)
return (FALSE);
if ((wp = popbuf(bp, WNONE)) == NULL)
return (FALSE);
curbp = bp;
compile_win = curwp = wp;
gotoline(FFARG, 0);
return (TRUE);
}
/* id-utils foo. */
/* ARGSUSED */
static int
gid(int f, int n)
{
char command[NFILEN];
char cprompt[NFILEN], c, *bufp;
struct buffer *bp;
struct mgwin *wp;
int i, j, len;
/* catch ([^\s(){}]+)[\s(){}]* */
i = curwp->w_doto;
/* Skip backwards over delimiters we are currently on */
while (i > 0) {
c = lgetc(curwp->w_dotp, i);
if (isalnum(c) || c == '_')
break;
i--;
}
/* Skip the symbol itself */
for (; i > 0; i--) {
c = lgetc(curwp->w_dotp, i - 1);
if (!isalnum(c) && c != '_')
break;
}
/* Fill the symbol in cprompt[] */
for (j = 0; j < sizeof(cprompt) - 1 && i < llength(curwp->w_dotp);
j++, i++) {
c = lgetc(curwp->w_dotp, i);
if (!isalnum(c) && c != '_')
break;
cprompt[j] = c;
}
cprompt[j] = '\0';
if ((bufp = eread("Run gid (with args): ", cprompt, NFILEN,
(j ? EFDEF : 0) | EFNEW | EFCR)) == NULL)
return (ABORT);
else if (bufp[0] == '\0')
return (FALSE);
len = snprintf(command, sizeof(command), "gid %s", cprompt);
if (len < 0 || len >= sizeof(command))
return (FALSE);
if ((bp = compile_mode("*gid*", command)) == NULL)
return (FALSE);
if ((wp = popbuf(bp, WNONE)) == NULL)
return (FALSE);
curbp = bp;
compile_win = curwp = wp;
return (TRUE);
}
struct buffer *
compile_mode(const char *name, const char *command)
{
struct buffer *bp;
FILE *fpipe;
char *buf;
size_t len;
int ret, n;
char cwd[NFILEN], qcmd[NFILEN];
char timestr[NTIME];
time_t t;
n = snprintf(qcmd, sizeof(qcmd), "%s 2>&1", command);
if (n < 0 || n >= sizeof(qcmd))
return (NULL);
bp = bfind(name, TRUE);
if (bclear(bp) != TRUE)
return (NULL);
if (getbufcwd(bp->b_cwd, sizeof(bp->b_cwd)) != TRUE)
return (NULL);
addlinef(bp, "cd %s", bp->b_cwd);
addline(bp, qcmd);
addline(bp, "");
if (getcwd(cwd, sizeof(cwd)) == NULL)
panic("Can't get current directory!");
if (chdir(bp->b_cwd) == -1) {
ewprintf("Can't change dir to %s", bp->b_cwd);
return (NULL);
}
if ((fpipe = popen(qcmd, "r")) == NULL) {
ewprintf("Problem opening pipe");
return (NULL);
}
/*
* We know that our commands are nice and the last line will end with
* a \n, so we don't need to try to deal with the last line problem
* in fgetln.
*/
while ((buf = fgetln(fpipe, &len)) != NULL) {
buf[len - 1] = '\0';
addline(bp, buf);
}
ret = pclose(fpipe);
t = time(NULL);
strftime(timestr, sizeof(timestr), "%a %b %e %T %Y", localtime(&t));
addline(bp, "");
if (ret != 0)
addlinef(bp, "Command exited abnormally with code %d"
" at %s", ret, timestr);
else
addlinef(bp, "Command finished at %s", timestr);
bp->b_dotp = bfirstlp(bp);
bp->b_modes[0] = name_mode("fundamental");
bp->b_modes[1] = name_mode("compile");
bp->b_nmodes = 1;
compile_buffer = bp;
if (chdir(cwd) == -1) {
ewprintf("Can't change dir back to %s", cwd);
return (NULL);
}
return (bp);
}
/* ARGSUSED */
static int
compile_goto_error(int f, int n)
{
struct buffer *bp;
struct mgwin *wp;
char *fname, *line, *lp, *ln;
int lineno;
char *adjf, path[NFILEN];
const char *errstr;
struct line *last;
compile_win = curwp;
compile_buffer = curbp;
last = blastlp(compile_buffer);
retry:
/* last line is compilation result */
if (curwp->w_dotp == last)
return (FALSE);
if ((line = linetostr(curwp->w_dotp)) == NULL)
return (FALSE);
lp = line;
if ((fname = strsep(&lp, ":")) == NULL || *fname == '\0')
goto fail;
if ((ln = strsep(&lp, ":")) == NULL || *ln == '\0')
goto fail;
lineno = (int)strtonum(ln, INT_MIN, INT_MAX, &errstr);
if (errstr)
goto fail;
if (fname && fname[0] != '/') {
if (getbufcwd(path, sizeof(path)) == FALSE)
goto fail;
if (strlcat(path, fname, sizeof(path)) >= sizeof(path))
goto fail;
adjf = path;
} else {
adjf = adjustname(fname, TRUE);
}
free(line);
if (adjf == NULL)
return (FALSE);
if ((bp = findbuffer(adjf)) == NULL)
return (FALSE);
if ((wp = popbuf(bp, WNONE)) == NULL)
return (FALSE);
curbp = bp;
curwp = wp;
if (bp->b_fname[0] == '\0')
readin(adjf);
gotoline(FFARG, lineno);
return (TRUE);
fail:
free(line);
if (curwp->w_dotp != blastlp(curbp)) {
curwp->w_dotp = lforw(curwp->w_dotp);
curwp->w_rflag |= WFMOVE;
goto retry;
}
ewprintf("No more hits");
return (FALSE);
}
/* ARGSUSED */
int
next_error(int f, int n)
{
if (compile_win == NULL || compile_buffer == NULL) {
ewprintf("No compilation active");
return (FALSE);
}
curwp = compile_win;
curbp = compile_buffer;
if (curwp->w_dotp == blastlp(curbp)) {
ewprintf("No more hits");
return (FALSE);
}
curwp->w_dotp = lforw(curwp->w_dotp);
curwp->w_rflag |= WFMOVE;
return (compile_goto_error(f, n));
}
/*
* Since we don't have variables (we probably should) these are command
* processors for changing the values of mode flags.
*/
/* ARGSUSED */
int
globalwdtoggle(int f, int n)
{
if (f & FFARG)
globalwd = n > 0;
else
globalwd = !globalwd;
sgarbf = TRUE;
return (TRUE);
}