Skip to content

Commit

Permalink
Ensure a stable view column search
Browse files Browse the repository at this point in the history
This (should) fix the tree/default-test.
  • Loading branch information
jonas committed Aug 29, 2014
1 parent 1fa3d0a commit 98e692b
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 50 deletions.
103 changes: 68 additions & 35 deletions src/view.c
Original file line number Diff line number Diff line change
Expand Up @@ -869,76 +869,109 @@ open_argv(struct view *prev, struct view *view, const char *argv[], const char *

static struct view *sorting_view;

#define sort_order_reverse(state, result) \
((state)->reverse ? -(result) : (result))

#define sort_order(state, cmp, o1, o2) \
sort_order_reverse(state, (!(o1) || !(o2)) ? !!(o2) - !!(o1) : cmp(o1, o2))
#define apply_comparator(cmp, o1, o2) \
(!(o1) || !(o2)) ? !!(o2) - !!(o1) : cmp(o1, o2)

#define number_compare(size1, size2) (*(size1) - *(size2))

#define mode_is_dir(mode) ((mode) && S_ISDIR(*(mode)))

static int
sort_view_compare(const void *l1, const void *l2)
compare_view_column(enum view_column_type column, bool use_file_mode,
const struct line *line1, struct view_column_data *column_data1,
const struct line *line2, struct view_column_data *column_data2)
{
const struct line *line1 = l1;
const struct line *line2 = l2;
struct view_column_data column_data1 = {};
struct view_column_data column_data2 = {};
struct sort_state *sort = &sorting_view->sort;

if (!sorting_view->ops->get_column_data(sorting_view, line1, &column_data1))
return -1;
else if (!sorting_view->ops->get_column_data(sorting_view, line2, &column_data2))
return 1;

switch (get_sort_field(sorting_view)) {
switch (column) {
case VIEW_COLUMN_AUTHOR:
return sort_order(sort, ident_compare, column_data1.author, column_data2.author);
return apply_comparator(ident_compare, column_data1->author, column_data2->author);

case VIEW_COLUMN_DATE:
return sort_order(sort, timecmp, column_data1.date, column_data2.date);
return apply_comparator(timecmp, column_data1->date, column_data2->date);

case VIEW_COLUMN_ID:
if (column_data1.reflog && column_data2.reflog)
return sort_order(sort, strcmp, column_data1.reflog, column_data2.reflog);
return sort_order(sort, strcmp, column_data1.id, column_data2.id);
if (column_data1->reflog && column_data2->reflog)
return apply_comparator(strcmp, column_data1->reflog, column_data2->reflog);
return apply_comparator(strcmp, column_data1->id, column_data2->id);

case VIEW_COLUMN_FILE_NAME:
if (mode_is_dir(column_data1.mode) != mode_is_dir(column_data2.mode))
return sort_order_reverse(sort, mode_is_dir(column_data1.mode) ? -1 : 1);
return sort_order(sort, strcmp, column_data1.file_name, column_data2.file_name);
if (use_file_mode && mode_is_dir(column_data1->mode) != mode_is_dir(column_data2->mode))
return mode_is_dir(column_data1->mode) ? -1 : 1;
return apply_comparator(strcmp, column_data1->file_name, column_data2->file_name);

case VIEW_COLUMN_FILE_SIZE:
return sort_order(sort, number_compare, column_data1.file_size, column_data2.file_size);
return apply_comparator(number_compare, column_data1->file_size, column_data2->file_size);

case VIEW_COLUMN_LINE_NUMBER:
return sort_order_reverse(sort, line1->lineno - line2->lineno);
return line1->lineno - line2->lineno;

case VIEW_COLUMN_MODE:
return sort_order(sort, number_compare, column_data1.mode, column_data2.mode);
return apply_comparator(number_compare, column_data1->mode, column_data2->mode);

case VIEW_COLUMN_REF:
return sort_order(sort, ref_compare, column_data1.ref, column_data2.ref);
return apply_comparator(ref_compare, column_data1->ref, column_data2->ref);

case VIEW_COLUMN_COMMIT_TITLE:
return sort_order(sort, strcmp, column_data1.commit_title, column_data2.commit_title);
return apply_comparator(strcmp, column_data1->commit_title, column_data2->commit_title);

case VIEW_COLUMN_SECTION:
return sort_order(sort, strcmp, column_data1.section->opt.section.text,
column_data2.section->opt.section.text);
return apply_comparator(strcmp, column_data1->section->opt.section.text,
column_data2->section->opt.section.text);

case VIEW_COLUMN_STATUS:
return sort_order(sort, number_compare, column_data1.status, column_data2.status);
return apply_comparator(number_compare, column_data1->status, column_data2->status);

case VIEW_COLUMN_TEXT:
return sort_order(sort, strcmp, column_data1.text, column_data2.text);
return apply_comparator(strcmp, column_data1->text, column_data2->text);
}

return 0;
}

static enum view_column_type view_column_order[] = {
VIEW_COLUMN_FILE_NAME,
VIEW_COLUMN_STATUS,
VIEW_COLUMN_MODE,
VIEW_COLUMN_FILE_SIZE,
VIEW_COLUMN_DATE,
VIEW_COLUMN_AUTHOR,
VIEW_COLUMN_COMMIT_TITLE,
VIEW_COLUMN_LINE_NUMBER,
VIEW_COLUMN_SECTION,
VIEW_COLUMN_TEXT,
VIEW_COLUMN_REF,
VIEW_COLUMN_ID,
};

static int
sort_view_compare(const void *l1, const void *l2)
{
const struct line *line1 = l1;
const struct line *line2 = l2;
struct view_column_data column_data1 = {};
struct view_column_data column_data2 = {};
struct sort_state *sort = &sorting_view->sort;
enum view_column_type column = get_sort_field(sorting_view);
int cmp;
int i;

if (!sorting_view->ops->get_column_data(sorting_view, line1, &column_data1))
return -1;
else if (!sorting_view->ops->get_column_data(sorting_view, line2, &column_data2))
return 1;

cmp = compare_view_column(column, TRUE, line1, &column_data1, line2, &column_data2);

/* Ensure stable sorting by ordering ordering by the other
* columns if the selected column values are equal. */
for (i = 0; !cmp && i < ARRAY_SIZE(view_column_order); i++)
if (column != view_column_order[i])
cmp = compare_view_column(view_column_order[i], FALSE,
line1, &column_data1,
line2, &column_data2);

return sort->reverse ? -cmp : cmp;
}

void
sort_view(struct view *view, bool change_field)
{
Expand Down
30 changes: 15 additions & 15 deletions test/tree/default-test
Original file line number Diff line number Diff line change
Expand Up @@ -58,34 +58,34 @@ EOF

assert_equals 'tree-default-author.screen' <<EOF
Directory path /
-rw-r--r-- Jonas Fonseca 53 2013-10-14 16:19 .gitignore
-rw-r--r-- Jonas Fonseca 1499 2013-10-26 12:54 LICENSE
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 common
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 deltablue
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 project
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 richards
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 tracer
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 sudoku
-rw-r--r-- Jonas Fonseca 53 2013-10-14 16:19 .gitignore
-rw-r--r-- Jonas Fonseca 1499 2013-10-26 12:54 LICENSE
-rwxr-xr-x Jonas Fonseca 493 2014-03-01 17:26 run.sh
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 sudoku
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 tracer
-rw-r--r-- Philipp Haller 2609 2014-01-16 15:32 README.md
[tree] 1a4ced7066ada2b26dcb0044f763a8438cd375df - file 1 of 10 100%
[tree] be06d7d413c0b3f2d2f6f18061c8bfb65c510b64 - file 7 of 10 100%
EOF

assert_equals 'tree-default-date.screen' <<EOF
Directory path /
-rw-r--r-- Jonas Fonseca 53 2013-10-14 16:19 .gitignore
-rw-r--r-- Jonas Fonseca 1499 2013-10-26 12:54 LICENSE
-rw-r--r-- Philipp Haller 2609 2014-01-16 15:32 README.md
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 richards
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 project
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 deltablue
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 common
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 deltablue
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 project
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 richards
-rwxr-xr-x Jonas Fonseca 493 2014-03-01 17:26 run.sh
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 tracer
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 sudoku
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 tracer
Expand All @@ -98,12 +98,12 @@ Directory path /
-rwxr-xr-x Jonas Fonseca 493 2014-03-01 17:26 run.sh
-rw-r--r-- Jonas Fonseca 1499 2013-10-26 12:54 LICENSE
-rw-r--r-- Philipp Haller 2609 2014-01-16 15:32 README.md
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 tracer
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 sudoku
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 richards
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 project
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 deltablue
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 common
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 deltablue
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 project
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 richards
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 sudoku
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 tracer
Expand All @@ -116,8 +116,8 @@ drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 common
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 deltablue
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 project
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 richards
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 tracer
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 sudoku
drwxr-xr-x Jonas Fonseca 2014-03-01 17:26 tracer
-rw-r--r-- Jonas Fonseca 53 2013-10-14 16:19 .gitignore
-rw-r--r-- Jonas Fonseca 1499 2013-10-26 12:54 LICENSE
-rw-r--r-- Philipp Haller 2609 2014-01-16 15:32 README.md
Expand Down

0 comments on commit 98e692b

Please sign in to comment.