Copyright (c) 2000, 2001, 2002, 2003, 2004 by Martin C. Shepherd. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, provided that the above
copyright notice(s) and this permission notice appear in all copies of
the Software and that both the above copyright notice(s) and this
permission notice appear in supporting documentation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Except as contained in this notice, the name of a copyright holder
shall not be used in advertising or otherwise to promote the sale, use
or other dealings in this Software without prior written authorization
of the copyright holder.
Portions Copyright (c) 2007, Sun Microsystems, Inc. All Rights Reserved.
cc [ flag.\|.\|. ] file.\|.\|. -ltecla [ library.\|.\|. ] #include <libtecla.h> char *pca_lookup_file(PathCache *pc, const char *name, int name_len, int literal);
PathCache *del_PathCache(PathCache *pc);
PcaPathConf *del_PcaPathConf(PcaPathConf *ppc);
PathCache *new_PathCache(void);
PcaPathConf *new_PcaPathConf(PathCache *pc);
const char *pca_last_error(PathCache *pc);
CPL_MATCH_FN(pca_path_completions);
int pca_scan_path(PathCache *pc, const char *path);
void pca_set_check_fn(PathCache *pc, CplCheckFn *check_fn, void *data);
void ppc_file_start(PcaPathConf *ppc, int start_index);
void ppc_literal_escapes(PcaPathConf *ppc, int literal);
#include <stdio.h> #include <stdlib.h> #include <libtecla.h> int main(int argc, char *argv[]) { int i; /* * Create a cache for executable files. */ PathCache *pc = new_PathCache(); if(!pc) exit(1); /* * Scan the user's PATH for executables. */ if(pca_scan_path(pc, getenv("PATH"))) { fprintf(stderr, "%s\en", pca_last_error(pc)); exit(1); } /* * Arrange to only report executable files. */ pca_set_check_fn(pc, cpl_check_exe, NULL); /* * Lookup and display the full pathname of each of the * commands listed on the command line. */ for(i=1; i<argc; i++) { char *cmd = pca_lookup_file(pc, argv[i], -1, 0); printf("The full pathname of '%s' is %s\e\en", argv[i], cmd ? cmd : "unknown"); } pc = del_PathCache(pc); /* Clean up */ return 0; }
The following is an example of what this does on a laptop under LINUX:
$ ./example less more blob The full pathname of 'less' is /usr/bin/less The full pathname of 'more' is /bin/more The full pathname of 'blob' is unknown $
On success this function return 0. On error it returns 1, and a description of the error can be obtained by calling pca_last_error(pc).
To make it possible to pass this function a filename which is actually part of a longer string, the name_len argument can be used to specify the length of the filename at the start of the name[] argument. If you pass -1 for this length, the length of the string will be determined with strlen. If the name[] string might contain backslashes that escape the special meanings of spaces and tabs within the filename, give the literal argument the value 0. Otherwise, if backslashes should be treated as normal characters, pass 1 for the value of the literal argument.
This callback requires that its data argument be a pointer to a PcaPathConf object. Configuration objects of this type are allocated by calling new_PcaPathConf().
This function returns an object initialized with default configuration parameters, which determine how the cpl_path_completions() callback function behaves. The functions which allow you to individually change these parameters are discussed below.
By default, the pca_path_completions() callback function searches backwards for the start of the filename being completed, looking for the first un-escaped space or the start of the input line. If you wish to specify a different location, call ppc_file_start() with the index at which the filename starts in the input line. Passing start_index=-1 re-enables the default behavior.
By default, when pca_path_completions() looks at a filename in the input line, each lone backslash in the input line is interpreted as being a special character which removes any special significance of the character which follows it, such as a space which should be taken as part of the filename rather than delimiting the start of the filename. These backslashes are thus ignored while looking for completions, and subsequently added before spaces, tabs and literal backslashes in the list of completions. To have unescaped backslashes treated as normal characters, call ppc_literal_escapes() with a non-zero value in its literal argument.
When you have finished with a PcaPathConf variable, you can pass it to the del_PcaPathConf() destructor function to reclaim its memory.
#define CPL_CHECK_FN(fn) int (fn)(void *data, const char *pathname) typedef CPL_CHECK_FN(CplCheckFn);
Registering one of these functions involves calling the pca_set_check_fn() function. In addition to the callback function passed with the check_fn argument, you can pass a pointer to anything with the data argument. This pointer will be passed on to your callback function by its own data argument whenever it is called, providing a way to pass application-specific data to your callback. Note that these callbacks are passed the full pathname of each matching file, so the decision about whether a file is of interest can be based on any property of the file, not just its filename. As an example, the provided cpl_check_exe() callback function looks at the executable permissions of the file and the permissions of its parent directories, and only returns 1 if the user has execute permission to the file. This callback function can thus be used to lookup or complete command names found in the directories listed in the user's PATH environment variable. The example program above provides a demonstration of this.
Beware that if somebody tries to complete an empty string, your callback will get called once for every file in the cache, which could number in the thousands. If your callback does anything time consuming, this could result in an unacceptable delay for the user, so callbacks should be kept short.
To improve performance, whenever one of these callbacks is called, the choice that it makes is cached, and the next time the corresponding file is looked up, instead of calling the callback again, the cached record of whether it was accepted or rejected is used. Thus if somebody tries to complete an empty string, and hits tab a second time when nothing appears to happen, there will only be one long delay, since the second pass will operate entirely from the cached dispositions of the files. These cached dispositions are discarded whenever pca_scan_path() is called, and whenever pca_set_check_fn() is called with changed callback function or data arguments.
ATTRIBUTE TYPE ATTRIBUTE VALUE |
Interface Stability Evolving |
MT-Level MT-Safe |