Lugaru's Epsilon Programmer's Editor 14.04
Context:
|
Previous
|
Up
|
Next
|
Completion Subroutines |
Primitives and EEL Subroutines |
Listing Commands & Buffers & Files |
Epsilon User's Manual and Reference >
Primitives and EEL Subroutines >
Input Primitives >
Completion Subroutines >
Completion Internals
/* bits for finder func */
#define STARTMATCH 1
#define EXACTONLY 2
#define LISTMATCH 4
#define FM_NO_DIRS (0x10)
#define FM_ONLY_DIRS (0x20)
char *b_match(char *partial, int flags)
/* sample finder */
comp_read(char *response, char *prmpt,
char *(*finder)(), int flags, char *def)
/* bits for comp_read() */
#define CAUTIOUS (0x100)
#define COMP_FOLD (0x200)
#define MUST_MATCH (0x400)
#define NONE_OK (0x800)
#define POP_UP_PROMPT (0x1000)
#define COMP_FILE (0x2000 | CAUTIOUS)
#define PASSWORD_PROMPT (0x4000)
#define SPACE_VALID (0x8000)
prompt_comp_read(char *response, char *prmpt,
char *(*finder)(), int flags,
char *def)
zeroed char completion_column_marker;
It's easy
to add new subroutines that can complete on other things. First, you
must write a "finder" function that returns each of the possible
matches, one at a time, for something the user has typed. For
example, the get_buf( ) subroutine uses the finder function
b_match( ).
A finder function takes a parameter partial which contains what
the user's typed so far, and a set of flags . If the
STARTMATCH flag is on, the function must return the first
match of partial . If STARTMATCH is off, it should return
the next match. The function should return 0 when there are no
more matches. The LISTMATCH flag is on when Epsilon is
preparing a list of choices because the user has pressed "?". This
is so that a finder function can format the results differently in
that case. If the EXACTONLY flag is on, the finder
function should return only exact matches for partial . If the
finder function is matching file names, you may also provide the
FM_NO_DIRS flag, to exclude directory names, or
FM_ONLY_DIRS to retrieve only directory names.
Next, write a subroutine like the various get_ routines described
above, all of which are defined in complete.e. It should take a
prompt string, possibly a default string, and a character pointer in
which to put the user's response. It passes these to the
comp_read( ) subroutine, along with the name of your finder
function (as a function pointer).
The comp_read( ) subroutine also takes a flags parameter.
If the CAUTIOUS flag is zero, comp_read( ) assumes that
all matches for a certain string will begin with that string, and
that if there is only one match for a certain string, adding
characters to that string won't generate any more matches. These
assumptions are true for most things Epsilon completes on, but
they're not true for files. (For example, if the only match for x is
xyz, but xyz is a directory with many files, the second assumption
would be false. The first assumption is false when Epsilon completes
on wildcard patterns like *.c , since none of the matches will
start with the * character.) If you provide the CAUTIOUS
flag when you call comp_read( ), Epsilon doesn't make those
assumptions, and completion is somewhat slower.
Actually, when completing on files, provide the COMP_FILE
macro instead of just CAUTIOUS; this includes CAUTIOUS
but also makes Epsilon use some special rules necessary for
completing on file names.
If you provide the COMP_FOLD flag to comp_read( ), it will
do case-folding when comparing possible completions.
The MUST_MATCH flag tells comp_read( ) that if the
user types a response that the finder function doesn't recognize,
it's probably a mistake. The comp_read( ) subroutine will then
offer a list of possible responses, even though the user may not have
pressed a key that ordinarily triggers completion. The
comp_read( ) subroutine might still return with an unrecognized
response, though. This flag is simply advice to comp_read( ).
The NONE_OK flag is used only with MUST_MATCH. It
tells comp_read( ) that an empty response (just typing
<Enter>) is ok.
Under Epsilon for Windows, the POP_UP_PROMPT flag tells
comp_read( ) to immediately pop up a one-line dialog box when
prompting. Right now, this flag may only be used when no completion
is involved, and comp_read( ) is simply prompting for a line of
text.
The PASSWORD_PROMPT flag tells comp_read( ) to display
each character of the response as a * character. When the
Internet functions prompt for a password they use this flag.
The SPACE_VALID flag tells comp_read( ) that a
<Space> character is valid in the response. Since <Space> is
also a completion character, comp_read( ) tries to guess whether
to add a <Space> or complete, by examining possible matches.
A finder function receives any of the above flags that were passed to
comp_read( ), so it can alter its behavior if it wants.
The comp_read( ) subroutine uses the prompt you supply as-is.
Usually, the prompt should end with a colon and a space, like
"Find file: " . By contrast, the prompt_comp_read( )
subroutine adds to the supplied prompt by showing the default value
inside square brackets, when insert-default-response is zero.
The prompt string you supply to it should not end with a colon and
space, since Epsilon will add these. If you provide a prompt such as
"Buffer name" and a default value of "main" , Epsilon will
display Buffer name [main]: . If the default value you provide
is empty or too long, Epsilon will instead display Buffer name: ,
omitting the default. Whether or not Epsilon displays the default,
if the user doesn't enter any text at the prompt the
prompt_comp_read( ) subroutine substitutes the default value by
copying def to response .
Sometimes it's convenient if a finder function returns matches with
additional data after them which shouldn't be included in the returned
response. You can set the variable completion_column_marker
to a character that marks the start of such extra data. If it's
nonzero, and a response from the finder function contains it, Epsilon
strips that character and any following text from the response before
returning it, if the user selects that choice from the list of
completions.
char *(*list_finder)();
list_matches(char *s, char *(*finder)(), int flags, int mbuf)
int *(*completion_lister)();
char resize_menu_list;
The comp_read( ) subroutine looks at several variables whenever
it needs to display a list of possible completions (such as when the
user types "?"). You can change the way Epsilon displays the list by
setting these variables. Typically, you would use the save_var
statement to temporarily set one of these while your completion
routine runs.
By default, Epsilon calls the list_matches( ) subroutine to
prepare its buffer of possible matches. The function takes the
string to complete on, the finder function to use, flags as described
above, and a buffer number. It calls the finder function repeatedly
(passing it the LISTMATCH flag as well as any others passed to
list_matches( )) and puts the resulting matches into the
indicated buffer, after sorting the matches. If the
completion_lister function pointer is non-null, Epsilon
calls that function instead of list_matches( ), passing it the
same parameters. If, for example, you have to sort the matches in a
special order, you can set this variable.
If you simply want a different list of matches when Epsilon lists
them, as opposed to when Epsilon completes on them, you can set the
list_finder function pointer to point to a different finder
function. The list_matches( ) subroutine always uses this
variable if non-null, instead of the finder function it receives as a
parameter.
An EEL completion function can temporarily set the
resize_menu_list variable nonzero to indicate that if the user
tries to list possible completion choices, the window displaying the
choices should be widened if necessary to fit the widest choice.
This variable has no effect on Epsilon windows within GUI dialogs.
int complete(char *response, char *(*finder)(), int flags)
To actually do completion, comp_read( ) calls the
complete( ) subroutine. It takes a finder function pointer,
flags like CAUTIOUS and COMP_FOLD described above, and a
string to complete on. It tries to extend the string with additional
characters from the matches, modifying it in place.
The complete( ) subroutine generally returns the number of
possible matches for the string. However, it may be able to
determine that no more completion is possible before reaching the
last match. For example, if the subroutine tries to complete on the
file name "foo", and encounters files named "foobar", "foobaz",
"foo3", "foo4" and so forth, it can determine on the third file
that no completion is possible. In this case, it returns 3 ,
even though there may be additional matches. It can only "give up
early" in this way when it has encountered two or more matches. So
when the subroutine returns a value of two or greater, there may be
additional matches not included in its count.
build_prompt(char *full, char *pr, char *def, int omit, int rel)
The build_prompt( ) subroutine helps construct the text of
a prompt. It copies the prompt pr to full, appending
the default value def to it (inside brackets).
If the combination would be too wide for the screen, the subroutine
abbreviates the default value. If even an abbreviated value would be
too wide, or if omit is nonzero, it omits the default from the
prompt entirely. If rel is nonzero, it assumes def is
an absolute pathname, and uses its relative form.
find_buffer_prefix(int buf, char *prefix)
The find_buffer_prefix( ) subroutine looks through all the
lines in the buffer buf to see if they all start with the same
string of characters. It puts any such common prefix shared by all
the lines in prefix . For instance, if the buffer contains three
lines "waters", "watering" and "waterfall", it would put the
string "water" in dest .
char *general_matcher(char *s, int flags)
Epsilon providers a general-purpose finder function called
general_matcher( ). An EEL function can perform completion
on some arbitrary list of words by putting the list of words in a
buffer named _MATCH_BUF (a macro defined in eel.h) and then
providing general_matcher( ) as a finder function to a subroutine
like comp_read( ). Call comp_read( ) with the
COMP_FOLD flag if you want general_matcher( ) to ignore
case when comparing.
char _doing_input;
keytable comp_tab, menu_tab, view_tab;
An EEL function can tell if Epsilon is currently prompting for a line
of input (or performing certain related tasks) by examining the
_doing_input variable. It's zero normally. While Epsilon
is inside the search_read( ) subroutine or related ones, getting a
search string from the user, it's set to DI_SEARCH . While
Epsilon is prompting for a line of some other type of input, it's set
to DI_LINEINPUT .
While the view_buf( ) subroutine (or a related one) is displaying
a pop-up window, _doing_input is set to either DI_VIEW
or DI_VIEWLAST , according to whether the last parameter
passed to view_buf( ) was zero or not.
When Epsilon prompts for input, it uses certain specialized key tables
in the buffer that accepts the input. It uses the comp_tab
key table for the one-line buffer where the user types a response, in
all the subroutines that accept a line of input (except in
search_read( ) and related subroutines that prompt for search
strings).
When Epsilon displays a list of possible matches, or previous
responses, or similar things, while getting a line of input, it uses
the menu_tab key table in the buffer displaying the list.
Finally, subroutines like view_buf( ) normally use the
view_tab key table to show a buffer in a pop-up window.
Previous
|
Up
|
Next
|
Completion Subroutines |
Primitives and EEL Subroutines |
Listing Commands & Buffers & Files |
Epsilon Programmer's Editor 14.04 manual. Copyright (C) 1984, 2021 by Lugaru Software Ltd. All rights reserved.
|