When disabling history go into 'levenshtein' distance sorting when typing.

This commit is contained in:
QC 2014-07-05 19:47:55 +02:00
parent e4017fb28c
commit 6a917315ce
2 changed files with 110 additions and 24 deletions

View File

@ -869,6 +869,59 @@ int window_match ( char **tokens, __attribute__( ( unused ) ) const char *input,
return match;
}
static int lev_sort ( const void *p1, const void *p2, void *arg )
{
const int *a = p1;
const int *b = p2;
int *distances = arg;
return distances[*a] - distances[*b];
}
static int levenshtein ( const char *s, const char *t )
{
int ls = strlen ( s ), lt = strlen ( t );
int d[ls + 1][lt + 1];
for ( int i = 0; i <= ls; i++ ) {
for ( int j = 0; j <= lt; j++ ) {
d[i][j] = -1;
}
}
int dist ( int i, int j )
{
if ( d[i][j] >= 0 ) {
return d[i][j];
}
int x;
if ( i == ls ) {
x = lt - j;
}
else if ( j == lt ) {
x = ls - i;
}
else if ( s[i] == t[j] ) {
x = dist ( i + 1, j + 1 );
}
else {
x = dist ( i + 1, j + 1 );
int y;
if ( ( y = dist ( i, j + 1 ) ) < x ) {
x = y;
}
if ( ( y = dist ( i + 1, j ) ) < x ) {
x = y;
}
x++;
}
return d[i][j] = x;
}
return dist ( 0, 0 );
}
MenuReturn menu ( char **lines, char **input, char *prompt, Time *time, int *shift,
menu_match_cb mmc, void *mmc_data, int *selected_line )
{
@ -1038,9 +1091,13 @@ MenuReturn menu ( char **lines, char **input, char *prompt, Time *time, int *shi
// filtered list
char **filtered = calloc ( num_lines, sizeof ( char* ) );
int *line_map = calloc ( num_lines, sizeof ( int ) );
int *distance = NULL;
if ( config.disable_history ) {
distance = calloc ( num_lines, sizeof ( int ) );
}
unsigned int filtered_lines = 0;
if ( input && *input ) {
if ( input && *input && strlen ( *input ) > 0 ) {
char **tokens = tokenize ( *input );
// input changed
@ -1050,10 +1107,19 @@ MenuReturn menu ( char **lines, char **input, char *prompt, Time *time, int *shi
// If each token was matched, add it to list.
if ( match ) {
line_map[j] = i;
filtered[j++] = lines[i];
filtered_lines++;
if ( config.disable_history ) {
distance[i] = levenshtein ( *input, lines[i] );
}
j++;
}
}
if ( config.disable_history ) {
qsort_r ( line_map, j, sizeof ( int ), lev_sort, distance );
}
for ( i = 0; i < j; i++ ) {
filtered[i] = lines[line_map[i]];
}
filtered_lines = j;
tokenize_free ( tokens );
}
@ -1362,6 +1428,7 @@ MenuReturn menu ( char **lines, char **input, char *prompt, Time *time, int *shi
}
// If something changed, refilter the list. (paste or text entered)
if ( refilter ) {
if ( strlen ( text->text ) > 0 ) {
char **tokens = tokenize ( text->text );
// input changed
@ -1371,12 +1438,32 @@ MenuReturn menu ( char **lines, char **input, char *prompt, Time *time, int *shi
// If each token was matched, add it to list.
if ( match ) {
line_map[j] = i;
filtered[j++] = lines[i];
if ( config.disable_history ) {
distance[i] = levenshtein ( text->text, lines[i] );
}
j++;
}
}
if ( config.disable_history ) {
qsort_r ( line_map, j, sizeof ( int ), lev_sort, distance );
}
for ( i = 0; i < j; i++ ) {
filtered[i] = lines[line_map[i]];
}
// Cleanup + bookkeeping.
filtered_lines = j;
tokenize_free ( tokens );
}
else{
int jin = 0;
for ( i = 0; i < num_lines; i++ ) {
filtered[jin] = lines[i];
line_map[jin] = i;
jin++;
filtered_lines++;
}
}
selected = MIN ( selected, j - 1 );
for (; j < num_lines; j++ ) {
@ -1395,8 +1482,6 @@ MenuReturn menu ( char **lines, char **input, char *prompt, Time *time, int *shi
break;
}
tokenize_free ( tokens );
}
// Update if requested.
if ( update ) {
@ -1432,6 +1517,7 @@ MenuReturn menu ( char **lines, char **input, char *prompt, Time *time, int *shi
free ( filtered );
free ( line_map );
free ( distance );
return retv;
}