Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Tab completition revised to use *last word* in line
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | trunk
Files: files | file ages | folders
SHA3-256: 085aee93df71b88ffba6e186baa554e95b25d4776b1e6817d61badf94d5b3386
User & Date: jmcclure 2020-04-02 14:41:24
Context
2020-04-02
14:41
Tab completition revised to use *last word* in line Leaf check-in: 085aee93df user: jmcclure tags: trunk
2020-04-01
01:11
Removed needless check check-in: d1087cd34f user: jmcclure tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to interrobang.c.

12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
#include <X11/Xatom.h>
#include <X11/Xft/Xft.h>

#define MAX 1024

#define ENV_CHAR  "iBangChar"
#define ENV_BANG  "iBangBang"
#define ENV_ARGS  "iBangArgs"

#define ENV_LINE  "iBangLine"
#define ENV_LAST  "iBangLast"
#define ENV_TEMP  "iBangTemp"
#define ENV_TAB   "iBangTabDir"
#define ENV_RUN   "iBangRunDir"

typedef union {







|
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <X11/Xatom.h>
#include <X11/Xft/Xft.h>

#define MAX 1024

#define ENV_CHAR  "iBangChar"
#define ENV_BANG  "iBangBang"
#define ENV_HEAD  "iBangHead"
#define ENV_TAIL  "iBangTail"
#define ENV_LINE  "iBangLine"
#define ENV_LAST  "iBangLast"
#define ENV_TEMP  "iBangTemp"
#define ENV_TAB   "iBangTabDir"
#define ENV_RUN   "iBangRunDir"

typedef union {
229
230
231
232
233
234
235
236
237
238
239
240







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
	return 0;
}


/* KEY BINDABLE ACTION FUNCTIONS */

void complete_run_helper(const Arg *arg, const char *path, int run) {
	char arg0[MAX], arg1[MAX], *p;
	pid_t pid;
	int fd[2];
	FILE *in;
	setenv(ENV_LINE, line, 1);







	strcpy(arg0, path);
	if (line[0] == bang) {
		p = strchr(line, ' ');
		if (p) { *p = '\0'; p++; }
		strcat(arg0, line + 1);
		arg1[0] = bang;
		arg1[1] = '\0';
		setenv(ENV_CHAR, arg1, 1);
		setenv(ENV_BANG, line + 1, 1);
		strcpy(arg1, p ? p : "");
	}
	else {
		strcat(arg0, arg->v);
		strcpy(arg1, line);
		setenv(ENV_CHAR, "", 1);
		setenv(ENV_BANG, "", 1);
	}
	setenv(ENV_ARGS, arg1, 1);
	pipe(fd);
	pid = fork();
	if (pid == 0) {
		close(fd[0]);
		if (run) close(fd[1]);
		else dup2(fd[1], STDOUT_FILENO);
		execl(arg0, arg0, arg1, NULL);
		fprintf(stderr, "%s for '%s' not found\n",
				run ? "Runner": "Completer",
				line[0] == bang ? getenv(ENV_BANG) : arg->v);
		_exit(1);
	}
	else {
		close(fd[1]);







|




>
>
>
>
>
>
>



|

<
<
|

<



<



<






|







230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253


254
255

256
257
258

259
260
261

262
263
264
265
266
267
268
269
270
271
272
273
274
275
	return 0;
}


/* KEY BINDABLE ACTION FUNCTIONS */

void complete_run_helper(const Arg *arg, const char *path, int run) {
	char arg0[MAX], *p;
	pid_t pid;
	int fd[2];
	FILE *in;
	setenv(ENV_LINE, line, 1);
	strcpy(arg0, line);
	for (p = arg0 + strlen(arg0); p > arg0; p--)
		if (*p == ' ' && (p == arg0 || *(p-1) != '\\')) break;
	if (*p == ' ') p++;
	setenv(ENV_TAIL, p, 1);
	*p = '\0';
	setenv(ENV_HEAD, arg0, 1);
	strcpy(arg0, path);
	if (line[0] == bang) {
		p = strchr(line, ' ');
		if (p) *p = '\0';
		strcat(arg0, line + 1);


		setenv(ENV_CHAR, (const char []) { bang, '\0' }, 1);
		setenv(ENV_BANG, line + 1, 1);

	}
	else {
		strcat(arg0, arg->v);

		setenv(ENV_CHAR, "", 1);
		setenv(ENV_BANG, "", 1);
	}

	pipe(fd);
	pid = fork();
	if (pid == 0) {
		close(fd[0]);
		if (run) close(fd[1]);
		else dup2(fd[1], STDOUT_FILENO);
		execl(arg0, arg0, NULL);
		fprintf(stderr, "%s for '%s' not found\n",
				run ? "Runner": "Completer",
				line[0] == bang ? getenv(ENV_BANG) : arg->v);
		_exit(1);
	}
	else {
		close(fd[1]);

Changes to run/default.

1
2
3
#!/bin/sh

eval ${iBangArgs}


|
1
2
3
#!/bin/sh

eval ${iBangLine}

Changes to run/desk.

1
2

3
4
5
6


7

8

#!/bin/sh
# dependencies: dex


deskPath=/usr/share/applications
deskRunner=dex



# Note: if more than 1 file matches the basename, each of them will open in sequence

find ${deskPath} -name "${iBangArgs}*.desktop" -exec ${deskRunner} '{}' \;



>




>
>

>
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
# dependencies: dex
# I don't use .desktop files, so this runner gets *very* little testing and may not work at all.

deskPath=/usr/share/applications
deskRunner=dex

set -- ${iBangLine}
shift
# Note: if more than 1 file matches the basename, each of them will open in sequence
for desktop in $@; do
	find ${deskPath} -name "${desktop}.desktop" -exec ${deskRunner} '{}' \;
done

Changes to run/pdf.

1
2
3
4
5
6



7

#!/bin/sh

pdfPath=${HOME}
pdfViewer=mupdf

# Note: if more than 1 file matches the basename, each of them will open in sequence



find ${pdfPath} -name "${iBangArgs}*.pdf" -exec ${pdfViewer} '{}' \;






|
>
>
>
|
>
1
2
3
4
5
6
7
8
9
10
11
#!/bin/sh

pdfPath=${HOME}
pdfViewer=mupdf

# Note: if more than 1 file matches the basename (e.g., in different paths), each of them will open in sequence
set -- ${iBangLine}
shift
for pdfname in $@; do
	find ${pdfPath} -name "${pdfname}*.pdf" -exec ${pdfViewer} '{}' \;
done

Changes to run/term.

1
2
3
4
5


#!/bin/sh

term=st

${term} -e ${iBangArgs}




|

|
>
>
1
2
3
4
5
6
7
#!/bin/sh

# Change 'st' below to your desired terminal and ensure the -e flag is correct for it

set -- ${iBangLine}
shift
st -e "$@"

Changes to run/web.

1
2
3
4
5
#!/bin/sh

[ -z "${iBangArgs}" ] && exit

${BROWSER:-qutebrowser} "${iBangArgs}" >/dev/null 2>&1 &


|
|
|
1
2
3
4
5
#!/bin/sh

set -- ${iBangLine}
shift
${BROWSER:-qutebrowser} "$*" >/dev/null 2>&1 &

Changes to tab/calc.

1
2
3
4
5
6

7


#!/bin/sh
# dependencies: bc

echo "${iBangArgs}" \
	| bc \
	| sed "s/^/${iBangChar}${iBangBang} /;s/^ *//"




|
<

<
<
<
>

>
>
1

2



3
4
5
6
#!/bin/python





from os import environ

bang, eq = environ.get('iBangLine', '').split(' ', 2)
print(f'{bang} {eval(eq)}')

Changes to tab/default.

1
2



3





4

5




6
7
8
9
10
11





12

13
14

15
16
17



18


#!/bin/sh




# if the current line matches the last completition provided, send next one





if [ "${iBangLast}" == "${iBangLine}" ] && [ -f ${iBangTemp} ]; then

	sed -n "/^${iBangLast}$/{n;p;q}" ${iBangTemp}




	exit
fi

# other wise, generate new completition list
find $(echo $PATH | tr ':' ' ') \
	-name "${iBangArgs}*" \





	-exec basename '{}' \; \

	| sort -u \
	| sed "s/^/${iBangChar}${iBangBang} /;s/^ *//" \

	>| ${iBangTemp}

# send first option, and append to end of the list to allow for cycling the list



sed 1q ${iBangTemp} | tee -a ${iBangTemp}


|

>
>
>
|
>
>
>
>
>
|
>
|
>
>
>
>
|
<

|
<
|
>
>
>
>
>
|
>
|
<
>
|

|
>
>
>
|
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21

22
23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
#!/bin/python

from sys import exit, stdout
from os import chdir, environ, path
from glob import glob

iBangHead = environ.get('iBangHead', '')
iBangTail = environ.get('iBangTail', '')
iBangLast = environ.get('iBangLast', '')
iBangLine = environ.get('iBangLine', '')
iBangTemp = environ.get('iBangTemp', '/tmp/interrobang0')

# If the current line matches the last one sent, send next and exit:
if iBangLast == iBangLine:
    with open(iBangTemp, 'r') as fd:
        opts = fd.readlines()
    if iBangLine + '\n' in opts:
        stdout.write(opts[opts.index(iBangLine + '\n') + 1])
        exit(0)


# If the current line is a single "word", generate list from commands in path:

if iBangTail == iBangLine:
    opts = []
    for pathdir in environ.get('PATH', '/usr/bin').split(':'):
        chdir(pathdir)
        opts = opts + glob(iBangTail + '*')
    opts = list(set(opts))

# Or else complete the last word as a filename:
else:

    opts = [ x + '/' if path.isdir(x) else x for x in glob(iBangTail + '*') ]
    opts = [ iBangHead + x for x in opts ]

# Print list to temp file and return first entry:
if len(opts) > 0:
    opts = [ x + '\n' for x in opts ]
    opts.append(opts[0])
    with open(iBangTemp, 'w') as fd:
        fd.writelines(opts)
    stdout.write(opts[0].strip())

Changes to tab/desk.

1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16
17
18
#!/bin/sh

deskPath=/usr/share/applications

# if the current line matches the last completition provided, send next one
if [ "${iBangLast}" == "${iBangLine}" ] && [ -f ${iBangTemp} ]; then
	sed -n "/^${iBangLast}$/{n;p;q}" ${iBangTemp}
	exit
fi

# other wise, generate new completition list

find ${deskPath} -name "${iBangArgs}*.desktop" -exec basename '{}' .desktop \; \
	| sort -u \
	| sed "s/^/${iBangChar}${iBangBang} /;s/^ *//" \
	>| ${iBangTemp}

# send first option, and append to end of the list to allow for cycling the list
sed 1q ${iBangTemp} | tee -a ${iBangTemp}











>
|

|




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/sh

deskPath=/usr/share/applications

# if the current line matches the last completition provided, send next one
if [ "${iBangLast}" == "${iBangLine}" ] && [ -f ${iBangTemp} ]; then
	sed -n "/^${iBangLast}$/{n;p;q}" ${iBangTemp}
	exit
fi

# other wise, generate new completition list
echo $iBangTail >&2
find ${deskPath} -name "${iBangTail}*.desktop" -exec basename '{}' .desktop \; \
	| sort -u \
	| sed "s/^/${iBangHead}/" \
	>| ${iBangTemp}

# send first option, and append to end of the list to allow for cycling the list
sed 1q ${iBangTemp} | tee -a ${iBangTemp}

Changes to tab/man.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/sh

manPath=/usr/share/man

# if the current line matches the last completition provided, send next one
if [ "${iBangLast}" == "${iBangLine}" ] && [ -f ${iBangTemp} ]; then
	sed -n "/^${iBangLast}$/{n;p;q}" ${iBangTemp}
	exit
fi

# other wise, generate new completition list
find ${manPath} -name "${iBangArgs}*.gz" -exec basename '{}' .gz \; \
	| sort -u \
	| sed "s/^/${iBangChar}${iBangBang} /;s/^ *//" \
	>| ${iBangTemp}

# send first option, and append to end of the list to allow for cycling the list
sed 1q ${iBangTemp} | tee -a ${iBangTemp}











|

|




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/sh

manPath=/usr/share/man

# if the current line matches the last completition provided, send next one
if [ "${iBangLast}" == "${iBangLine}" ] && [ -f ${iBangTemp} ]; then
	sed -n "/^${iBangLast}$/{n;p;q}" ${iBangTemp}
	exit
fi

# other wise, generate new completition list
find ${manPath} -name "${iBangTail}*.gz" -exec basename '{}' .gz \; \
	| sort -u \
	| sed "s/^/${iBangHead}/" \
	>| ${iBangTemp}

# send first option, and append to end of the list to allow for cycling the list
sed 1q ${iBangTemp} | tee -a ${iBangTemp}

Changes to tab/pdf.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

#!/bin/sh

pdfPath=${HOME}

# If the current line matches the last completition provided, send next one
if [ "${iBangLast}" == "${iBangLine}" ] && [ -f ${iBangTemp} ]; then
	sed -n "/^${iBangLast}$/{n;p;q}" ${iBangTemp}
	exit
fi

# Other wise, generate new completition list
find ${pdfPath} -name "${iBangArgs}*.pdf" -exec basename '{}' .pdf \; \
	| sort -u \
	| sed "s/^/${iBangChar}${iBangBang} /;s/^ *//" \
	>| ${iBangTemp}

# Send first option
# Also append it to the end of the list to allow for cycling through the list
sed 1q ${iBangTemp} | tee -a ${iBangTemp}












|

|





>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh

pdfPath=${HOME}

# If the current line matches the last completition provided, send next one
if [ "${iBangLast}" == "${iBangLine}" ] && [ -f ${iBangTemp} ]; then
	sed -n "/^${iBangLast}$/{n;p;q}" ${iBangTemp}
	exit
fi

# Other wise, generate new completition list
find ${pdfPath} -name "${iBangTail}*.pdf" -exec basename '{}' .pdf \; \
	| sort -u \
	| sed "s/^/${iBangHead}/" \
	>| ${iBangTemp}

# Send first option
# Also append it to the end of the list to allow for cycling through the list
sed 1q ${iBangTemp} | tee -a ${iBangTemp}