% File: read_with_description.sl -*- mode: SLang -*- % % Copyright (c) % 2006 Jörg Sommer % $Id: read_with_description.sl 160 2007-06-28 11:11:34Z joerg $ % % Description: This is an extention of the read_with_completion() function % to print a description beside the proposal in the completion % buffer to give the user an idea of what he selects. % % License: This program is free software; you can redistribute it and/or % modify it under the terms of the GNU General Public License as % published by the Free Software Foundation; either version 2 of % the License, or (at your option) any later version. % % This program is distributed in the hope that it will be % useful, but WITHOUT ANY WARRANTY; without even the implied % warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR % PURPOSE. See the GNU General Public License for more details. #ifnexists profile_on % profiling does not work with stack check enabled. autoload("enable_stack_check", "stkcheck"); try { enable_stack_check(); } catch OpenError: {} % stkcheck not found in the path #endif %!%+ %\variable{Integer_Type RWD_Match} %\synopsis{Defines what and how read_with_description() makes a match} %\description % This variable defines how a completion should get found for % read_with_description(). % 0 means the matching is case insensitiv and only with the text % 1 means the matching is case sensitiv and only with the text % 2 means the matching is case insensitiv and with the text and the % description % 3 means the matching is case sensitiv and with the text and the % description % % The default is 1. %\seealso{read_with_completion()} %!%- custom_variable("RWD_Match", 1); private variable completion_list, max_compl_width; private define rwd_complete() { variable old_buf = whatbuf(); variable line = line_as_string(), buffer_new = not bufferp("*Completions*"); setbuf("*Completions*"); if (buffer_new) { if (max_compl_width > SCREEN_WIDTH/2) max_compl_width = SCREEN_WIDTH/2; insert("!!! Use Page Up/Down keys to scroll this window. !!!\n"); foreach (completion_list) { variable item = (); !if ( strlen(item.compl) ) continue; insert(item.compl); whitespace(1 + max_compl_width - strlen(item.compl)); insert("--"); if ( strlen(item.desc) ) { insert_char(' '); insert(item.desc); } newline(); } set_buffer_modified_flag(0); CASE_SEARCH = RWD_Match & 1; set_status_line(" Completion buffer ", 0); __uninitialize(&completion_list); } variable possible_completions; if (LAST_KBD_COMMAND == "%rwd_complete%") { pop2buf("*Completions*"); if ( eobp() ) { bob(); () = down(1); } if ( is_line_hidden() ) skip_hidden_lines_forward(1); % if not all lines are hidden, we have a completion possible_completions = not eobp(); } else { bob(); possible_completions = 0; variable search_fun; if ( (RWD_Match & 2) != 0 ) search_fun = &ffind(); else search_fun = &looking_at(); while ( down(1) ) { if ( orelse {strlen(line) == 0} {@search_fun(line)} ) { set_line_hidden(0); ++possible_completions; } else set_line_hidden(1); } bob(); () = down(1); if (possible_completions == 1 and is_line_hidden() ) skip_hidden_lines_forward(1); } variable completion; if (possible_completions == 1) { bol(); push_mark(); skip_chars("^ \t"); completion = bufsubstr(); skip_hidden_lines_forward(1); } pop2buf(old_buf); setbuf(old_buf); switch (possible_completions) { case 0: % no completion error flush("No possible completion!"); } { case 1: % excactly on completion if (whatbuf() != old_buf) { % Fixme: find the real reason % this is a hack to see in the *traceback* buffer the buffer name variable buf = whatbuf(); throw InternalError; } delete_line(); insert(completion); } set_current_kbd_command("%rwd_complete%"); } %!%+ %\function{read_with_description} %\synopsis{Prompt the user for a string and give him a description of the completion} %\usage{String_Type read_with_description(prompt, dflt, init, list)} %\description % This is an extention of the read_with_completion() function to print a % description beside the proposal in the completion buffer to give the user an % idea of what he selects. % % The argument prompt is the prompt for the user, dflt is returned if the user % simply hits return, init is th value to use as initialisation of the answer % and list is an List_Type of Struct_Type with two componentes "compl" for the % completions and "desc" for the description of the completion. The values are % presented in the order they are in the list, e. g. you can determine the % sorting order. %\seealso{read_with_completion()} %!%- public define read_with_description(prompt, dflt, init, list) { max_compl_width = 0; foreach (list) { variable item = (), compl = item.compl, desc = item.desc; if ( strlen(compl) != strlen(str_delete_chars(compl, " \t\n\r")) ) throw InvalidParmError, "The completion \"" + compl + "\" contains a whitespace"; if (strlen(compl) > max_compl_width) max_compl_width = strlen(compl); if ( strlen(desc) != strlen(str_delete_chars(desc, "\r\n")) ) throw InvalidParmError, "The description \"" + desc + "\" of completion \"" + compl + "\" contains a linebreak"; } completion_list = list; if ( bufferp("*Completions*") ) { variable orig_buf = whatbuf(); setbuf("*Completions*"); set_buffer_modified_flag(0); % jump back that delbuf() does not delete the current buffer and % jump to an arbitrary buffer setbuf(orig_buf); delbuf("*Completions*"); } % mangle the keymap of the mini buffer definekey(&rwd_complete, "\t", "Mini_Map"); definekey(&rwd_complete, " ", "Mini_Map"); % mangle the color of hidden line indicator variable old_fg, old_bg; (old_fg, old_bg) = get_color("..."); set_color("...", old_bg, old_bg); try return read_with_completion("", prompt, dflt, init, 's'); finally { definekey("mini_complete", "\t", "Mini_Map"); definekey("mini_complete", " ", "Mini_Map"); set_color("...", old_fg, old_bg); if ( bufferp("*Completions*") ) { variable old_buf = whatbuf(); if ( buffer_visible("*Completions*") ) { pop2buf("*Completions*"); call("delete_window"); pop2buf(old_buf); } delbuf("*Completions*"); } } } provide("read_with_description");