Launcher: add filename completion
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
#include <dirent.h>
|
||||
|
||||
static char *complete_on_command(char*, size_t);
|
||||
static char *complete_on_files(char*, size_t);
|
||||
|
||||
void
|
||||
launcher_execute(Launcher launcher)
|
||||
@@ -102,6 +103,13 @@ launcher_execute(Launcher launcher)
|
||||
my_guitar_gently_wheeps = 0;
|
||||
break;
|
||||
case XK_Tab:
|
||||
/*
|
||||
* completion
|
||||
* if there is not space in buffer we
|
||||
* complete the command using complete_on_command.
|
||||
* Else we try to complete on filename using
|
||||
* complete_on_files.
|
||||
*/
|
||||
buf[pos] = '\0';
|
||||
if (lastwastab)
|
||||
tabhits++;
|
||||
@@ -114,7 +122,11 @@ launcher_execute(Launcher launcher)
|
||||
|
||||
if (pos)
|
||||
{
|
||||
complete = complete_on_command(tmpbuf, tabhits);
|
||||
if (strchr(tmpbuf, ' '))
|
||||
complete = complete_on_files(tmpbuf, tabhits);
|
||||
else
|
||||
complete = complete_on_command(tmpbuf, tabhits);
|
||||
|
||||
if (complete)
|
||||
{
|
||||
strcpy(buf, tmpbuf);
|
||||
@@ -185,6 +197,10 @@ uicb_launcher(uicb_t cmd)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Just search command in PATH.
|
||||
* Return the characters to complete the command.
|
||||
*/
|
||||
static char *
|
||||
complete_on_command(char *start, size_t hits)
|
||||
{
|
||||
@@ -201,6 +217,7 @@ complete_on_command(char *start, size_t hits)
|
||||
path = _strdup(getenv("PATH"));
|
||||
dirname = strtok(path, ":");
|
||||
|
||||
/* recursively open PATH */
|
||||
while (dirname)
|
||||
{
|
||||
if ((dir = opendir(dirname)))
|
||||
@@ -225,3 +242,67 @@ complete_on_command(char *start, size_t hits)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Complete a filename or directory name.
|
||||
* works like complete_on_command.
|
||||
*/
|
||||
static char *
|
||||
complete_on_files(char *start, size_t hits)
|
||||
{
|
||||
char *ret = NULL;
|
||||
char *p;
|
||||
char *dirname = NULL;
|
||||
DIR *dir;
|
||||
struct dirent *content;
|
||||
size_t count = 0;
|
||||
|
||||
if (!start || hits <= 0 || !(p = strrchr(start, ' ')))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Search the directory to open and set
|
||||
* the beginning of file to complete on pointer 'p'.
|
||||
*/
|
||||
if (*(++p) == '\0' || !strrchr(p, '/'))
|
||||
dir = opendir(".");
|
||||
else
|
||||
{
|
||||
dirname = _strdup(p);
|
||||
p = strrchr(dirname, '/');
|
||||
if (p != dirname)
|
||||
{
|
||||
*(p++) = '\0';
|
||||
dir = opendir(dirname);
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = opendir("/");
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (dir)
|
||||
{
|
||||
while ((content = readdir(dir)))
|
||||
{
|
||||
if (!strcmp(content->d_name, ".") || !strcmp(content->d_name, ".."))
|
||||
continue;
|
||||
if (!strncmp(content->d_name, p, strlen(p)) && ++count == hits)
|
||||
{
|
||||
/* If it's a directory append '/' to the completion
|
||||
* TODO : content type can be a link to a directory check that
|
||||
*/
|
||||
if (content->d_type == DT_DIR)
|
||||
asprintf(&ret, "%s/", content->d_name + strlen(p));
|
||||
else
|
||||
ret = _strdup(content->d_name + strlen(p));
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
IFREE(dirname);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user