Repository: saulpw/visidata

Issue:
[sort] sort ordering is improperly copied in copy()
**Small description**
When I set a sort direction with `[` and copy a sheet (as with `"`), the sort direction disappears in the new sheet,.

**Expected result**
I expect the sort columns to be preserved in the copy. Or to disappear in all cases.

**Actual result with screenshot**
Any ordering I create myself, is lost.
But some orderings are preserved in the copy, the built-in ones that use a column name (a string), instead of the column object. Like FreqTableSheet's `'count'`.

**Steps to reproduce with sample data and a .vd**
Assign a sort direction to any column with `[` and duplicate the sheet with `g"`. The sort direction will not exist on the new sheet.

**Additional context**
visidata 2.11.1 and v3.0dev
The sort ordering is preserved across a copy, but too literally. After `copy()`, `sheet._ordering` contains columns, but they are the column objects from the source sheet, not the ones in the new copy. I can try to reconstruct the appropriate `_ordering`, like so:
https://github.com/saulpw/visidata/commit/f7bd9ef65ef5f0f230460b94ebdf4960ed2f2a7e
But I run into a problem. The `_ordering` I make is later overwritten with an empty list. It happens because `Extensible.init()` runs the `initfunc` for `_ordering`, which is `list`. How should I handle that?


Discussion:

Resolving patch:
diff --git a/visidata/sheets.py b/visidata/sheets.py
--- a/visidata/sheets.py
+++ b/visidata/sheets.py
@@ -314,14 +314,21 @@ def __copy__(self):
         ret.rows = UNLOADED
 
         ret.columns = []
-        for c in self.keyCols:
-            ret.addColumn(copy(c))
-
-        ret.setKeys(ret.columns)
 
+        col_mapping = {}
         for c in self.columns:
-            if c not in self.keyCols:
-                ret.addColumn(copy(c))
+            new_col = copy(c)
+            col_mapping[c] = new_col
+            ret.addColumn(new_col)
+
+        ret.setKeys([col_mapping[c] for c in self.columns if c.keycol])
+
+        ret._ordering = []
+        for sortcol,reverse in self._ordering:
+            if isinstance(sortcol, str):
+                ret._ordering.append((sortcol,reverse))
+            else:
+                ret._ordering.append((col_mapping[sortcol],reverse))
 
         ret.topRowIndex = ret.cursorRowIndex = 0
         return ret
@@ -1098,7 +1105,7 @@ def _async_deepcopy(newlist, oldlist):
 
 BaseSheet.init('pane', lambda: 1)
 
-Sheet.init('_ordering', list, copy=True)  # (col:Column, reverse:bool)
+Sheet.init('_ordering', list, copy=False)  # (col:Column, reverse:bool)
 
 
 BaseSheet.addCommand('^R', 'reload-sheet', 'preloadHook(); reload()', 'Reload current sheet')


Test patch:
diff --git a/tests/golden/issue2190.tsv b/tests/golden/issue2190.tsv
new file mode 100644
--- /dev/null
+++ b/tests/golden/issue2190.tsv
@@ -0,0 +1,44 @@
+OrderDate	Region	Rep	Item	Units	Unit_Cost	Total
+2016-04-18	Central	Andrews	Pencil	75	1.99	149.25
+2017-04-10	Central	Andrews	Pencil	66	1.99	131.34
+2017-10-31	Central	Andrews	Pencil	14	1.29	18.06
+2017-12-21	Central	Andrews	Binder	28	4.99	139.72
+2017-05-14	Central	Gill	Pencil	53	1.29	68.37
+2017-09-10	Central	Gill	Pencil	7	1.29	9.03
+2016-02-26	Central	Gill	Pen	27	19.99	539.73
+2017-01-15	Central	Gill	Binder	46	8.99	413.54
+2017-05-31	Central	Gill	Binder	80	8.99	719.20
+2016-02-09	Central	Jardine	Pencil	36	4.99	179.64
+2016-05-05	Central	Jardine	Pencil	90	4.99	449.10
+2017-03-24	Central	Jardine	Pen Set	50	4.99	249.50
+2017-11-17	Central	Jardine	Binder	11	4.99	54.89
+2017-12-04	Central	Jardine	Binder	94	19.99	1879.06
+2016-11-25	Central	Kivell	Pen Set	96	4.99	479.04
+2017-08-07	Central	Kivell	Pen Set	42	23.95	1005.90
+2017-06-17	Central	Kivell	Desk	5	125.00	625.00
+2016-01-23	Central	Kivell	Binder	50	19.99	999.50
+2016-06-25	Central	Morgan	Pencil	90	4.99	449.10
+2017-07-21	Central	Morgan	Pen Set	55	12.49	686.95
+2016-10-05	Central	Morgan	Binder	28	8.99	251.72
+2016-12-12	Central	Smith	Pencil	67	1.29	86.43
+2016-09-01	Central	Smith	Desk	2	125.00	250.00
+2017-02-01	Central	Smith	Binder	87	15.00	1305.00
+2017-04-27	East	Howard	Pen	96	4.99	479.04
+2016-07-12	East	Howard	Binder	29	1.99	57.71
+2016-01-06	East	Jones	Pencil	95	1.99	189.05
+2016-08-15	East	Jones	Pencil	35	4.99	174.65
+2016-09-18	East	Jones	Pen Set	16	15.99	255.84
+2017-07-04	East	Jones	Pen Set	62	4.99	309.38
+2016-10-22	East	Jones	Pen	64	8.99	575.36
+2016-04-01	East	Jones	Binder	60	4.99	299.40
+2016-06-08	East	Jones	Binder	60	8.99	539.40
+2017-02-18	East	Jones	Binder	4	4.99	19.96
+2016-12-29	East	Parent	Pen Set	74	15.99	1183.26
+2016-11-08	East	Parent	Pen	15	19.99	299.85
+2016-07-29	East	Parent	Binder	81	19.99	1619.19
+2016-03-15	West	Sorvino	Pencil	56	2.99	167.44
+2017-09-27	West	Sorvino	Pen	76	1.99	151.24
+2017-08-24	West	Sorvino	Desk	3	275.00	825.00
+2017-03-07	West	Sorvino	Binder	7	19.99	139.93
+2016-05-22	West	Thompson	Pencil	32	1.99	63.68
+2017-10-14	West	Thompson	Binder	57	19.99	1139.43
diff --git a/tests/issue2190.vdj b/tests/issue2190.vdj
new file mode 100644
--- /dev/null
+++ b/tests/issue2190.vdj
@@ -0,0 +1,8 @@
+#!vd -p
+{"sheet": null, "col": null, "row": null, "longname": "open-file", "input": "sample_data/sample.tsv", "keystrokes": "o", "comment": null}
+{"sheet": "sample", "col": "Region", "row": "", "longname": "sort-asc", "input": "", "keystrokes": "[", "comment": "sort ascending by current column; replace any existing sort criteria"}
+{"sheet": "sample", "col": "Rep", "row": "", "longname": "sort-asc-add", "input": "", "keystrokes": "z[", "comment": "sort ascending by current column; add to existing sort criteria"}
+{"sheet": "sample", "col": "Item", "row": "", "longname": "sort-desc-add", "input": "", "keystrokes": "z]", "comment": "sort descending by current column; add to existing sort criteria"}
+{"sheet": "sample", "col": "", "row": "", "longname": "select-rows", "input": "", "keystrokes": "gs", "comment": "select all rows"}
+{"sheet": "sample", "col": "", "row": "", "longname": "dup-selected", "input": "", "keystrokes": "\"", "comment": "open a duplicate sheet with only the selected rows"}
+{"sheet": "sample_selectedref", "col": "", "row": "", "longname": "unselect-rows", "input": "", "keystrokes": "gu", "comment": "unselect all rows"}