Repository: saulpw/visidata

Issue:
[v2.-4dev] Issues with sliding columns
From @anjakefala 


> Two issues:
- [x] Key columns cannot be re-arranged.
- [x] When a regular column reaches into the key column space, with `slide-left`, it can snap back to its starting position. It should just remain to the right of the key column space.
>
> This issue will be closed after both of these are investigated. Attempting a fix is preferable, but if a fix is too tricky, then this will be documented in /limits before closure.


Discussion:
https://asciinema.org/a/piLhBZPSdftMzic4abWUInQMF

Resolving patch:
diff --git a/visidata/slide.py b/visidata/slide.py
--- a/visidata/slide.py
+++ b/visidata/slide.py
@@ -7,6 +7,12 @@ def slide_col(sheet, colidx, newcolidx):
     vd.addUndo(moveVisibleCol, sheet, newcolidx, colidx)
     return moveVisibleCol(sheet, colidx, newcolidx)
 
+@Sheet.api
+def slide_keycol(sheet, fromKeyColIdx, toKeyColIdx):
+    vd.addUndo(moveKeyCol, sheet, toKeyColIdx, fromKeyColIdx)
+    return moveKeyCol(sheet, fromKeyColIdx, toKeyColIdx)
+
+
 @Sheet.api
 def slide_row(sheet, rowidx, newcolidx):
     vd.addUndo(moveListItem, sheet.rows, newcolidx, rowidx)
@@ -33,6 +39,25 @@ def onRelease(sheet, vcolidx, rowidx, destx, desty):
         sheet.onClick(vcolidx, rowidx)
 
 
+def moveKeyCol(sheet, fromKeyColIdx, toKeyColIdx):
+    'Move key column to another key column position in sheet.'
+    if not (1 <= toKeyColIdx <= len(sheet.keyCols)):
+        vd.fail('already at edge')
+
+    for col in sheet.keyCols:
+        if col.keycol == fromKeyColIdx:
+            col.keycol = toKeyColIdx
+        elif toKeyColIdx < fromKeyColIdx:  # moving to the left
+            if toKeyColIdx <= col.keycol < fromKeyColIdx:
+                col.keycol += 1
+        else:  # moving to the right
+            if 1 < col.keycol <= toKeyColIdx:
+                col.keycol -= 1
+
+    # key columns are 1-indexed; columns in general are 0-indexed
+    return toKeyColIdx-1
+
+
 def moveVisibleCol(sheet, fromVisColIdx, toVisColIdx):
     'Move visible column to another visible index in sheet.'
     if 0 <= toVisColIdx < sheet.nVisibleCols:
@@ -49,12 +74,12 @@ def moveVisibleCol(sheet, fromVisColIdx, toVisColIdx):
         vd.fail('already at edge')
 
 
-Sheet.addCommand('H', 'slide-left', 'sheet.cursorVisibleColIndex = slide_col(cursorVisibleColIndex, cursorVisibleColIndex-1)', 'slide current column left')
-Sheet.addCommand('L', 'slide-right', 'sheet.cursorVisibleColIndex = slide_col(cursorVisibleColIndex, cursorVisibleColIndex+1)', 'slide current column right')
+Sheet.addCommand('H', 'slide-left', 'sheet.cursorVisibleColIndex = slide_col(cursorVisibleColIndex, cursorVisibleColIndex-1) if not cursorCol.keycol else slide_keycol(cursorCol.keycol, cursorCol.keycol-1)', 'slide current column left')
+Sheet.addCommand('L', 'slide-right', 'sheet.cursorVisibleColIndex = slide_col(cursorVisibleColIndex, cursorVisibleColIndex+1) if not cursorCol.keycol else slide_keycol(cursorCol.keycol, cursorCol.keycol+1)', 'slide current column right')
 Sheet.addCommand('J', 'slide-down', 'sheet.cursorRowIndex = slide_row(cursorRowIndex, cursorRowIndex+1)', 'slide current row down')
 Sheet.addCommand('K', 'slide-up', 'sheet.cursorRowIndex = slide_row(cursorRowIndex, cursorRowIndex-1)', 'slide current row up')
-Sheet.addCommand('gH', 'slide-leftmost', 'slide_col(cursorVisibleColIndex, 0)', 'slide current column all the way to the left of sheet')
-Sheet.addCommand('gL', 'slide-rightmost', 'slide_col(cursorVisibleColIndex, nVisibleCols-1)', 'slide current column all the way to the right of sheet')
+Sheet.addCommand('gH', 'slide-leftmost', 'slide_col(cursorVisibleColIndex, 0) if not cursorCol.keycol else slide_keycol(cursorCol.keycol, 1)', 'slide current column all the way to the left of sheet')
+Sheet.addCommand('gL', 'slide-rightmost', 'slide_col(cursorVisibleColIndex, nVisibleCols-1) if not cursorCol.keycol else slide_keycol(cursorCol.keycol, len(keyCols))', 'slide current column all the way to the right of sheet')
 Sheet.addCommand('gJ', 'slide-bottom', 'slide_row(cursorRowIndex, nRows)', 'slide current row all the way to the bottom of sheet')
 Sheet.addCommand('gK', 'slide-top', 'slide_row(cursorRowIndex, 0)', 'slide current row to top of sheet')
 Sheet.addCommand('zH', 'slide-left-n', 'slide_col(cursorVisibleColIndex, cursorVisibleColIndex-int(input("slide col left n=", value=1)))', 'slide current column N positions to the left')


Test patch:
diff --git a/tests/golden/slide-keycol-1.tsv b/tests/golden/slide-keycol-1.tsv
new file mode 100644
--- /dev/null
+++ b/tests/golden/slide-keycol-1.tsv
@@ -0,0 +1,44 @@
+Rep	OrderDate	Region	Item	Units	Unit_Cost	Total
+Jones	2016-01-06	East	Pencil	95	1.99	189.05
+Kivell	2016-01-23	Central	Binder	50	19.99	999.50
+Jardine	2016-02-09	Central	Pencil	36	4.99	179.64
+Gill	2016-02-26	Central	Pen	27	19.99	539.73
+Sorvino	2016-03-15	West	Pencil	56	2.99	167.44
+Jones	2016-04-01	East	Binder	60	4.99	299.40
+Andrews	2016-04-18	Central	Pencil	75	1.99	149.25
+Jardine	2016-05-05	Central	Pencil	90	4.99	449.10
+Thompson	2016-05-22	West	Pencil	32	1.99	63.68
+Jones	2016-06-08	East	Binder	60	8.99	539.40
+Morgan	2016-06-25	Central	Pencil	90	4.99	449.10
+Howard	2016-07-12	East	Binder	29	1.99	57.71
+Parent	2016-07-29	East	Binder	81	19.99	1619.19
+Jones	2016-08-15	East	Pencil	35	4.99	174.65
+Smith	2016-09-01	Central	Desk	2	125.00	250.00
+Jones	2016-09-18	East	Pen Set	16	15.99	255.84
+Morgan	2016-10-05	Central	Binder	28	8.99	251.72
+Jones	2016-10-22	East	Pen	64	8.99	575.36
+Parent	2016-11-08	East	Pen	15	19.99	299.85
+Kivell	2016-11-25	Central	Pen Set	96	4.99	479.04
+Smith	2016-12-12	Central	Pencil	67	1.29	86.43
+Parent	2016-12-29	East	Pen Set	74	15.99	1183.26
+Gill	2017-01-15	Central	Binder	46	8.99	413.54
+Smith	2017-02-01	Central	Binder	87	15.00	1305.00
+Jones	2017-02-18	East	Binder	4	4.99	19.96
+Sorvino	2017-03-07	West	Binder	7	19.99	139.93
+Jardine	2017-03-24	Central	Pen Set	50	4.99	249.50
+Andrews	2017-04-10	Central	Pencil	66	1.99	131.34
+Howard	2017-04-27	East	Pen	96	4.99	479.04
+Gill	2017-05-14	Central	Pencil	53	1.29	68.37
+Gill	2017-05-31	Central	Binder	80	8.99	719.20
+Kivell	2017-06-17	Central	Desk	5	125.00	625.00
+Jones	2017-07-04	East	Pen Set	62	4.99	309.38
+Morgan	2017-07-21	Central	Pen Set	55	12.49	686.95
+Kivell	2017-08-07	Central	Pen Set	42	23.95	1005.90
+Sorvino	2017-08-24	West	Desk	3	275.00	825.00
+Gill	2017-09-10	Central	Pencil	7	1.29	9.03
+Sorvino	2017-09-27	West	Pen	76	1.99	151.24
+Thompson	2017-10-14	West	Binder	57	19.99	1139.43
+Andrews	2017-10-31	Central	Pencil	14	1.29	18.06
+Jardine	2017-11-17	Central	Binder	11	4.99	54.89
+Jardine	2017-12-04	Central	Binder	94	19.99	1879.06
+Andrews	2017-12-21	Central	Binder	28	4.99	139.72
diff --git a/tests/golden/slide-keycol-2.tsv b/tests/golden/slide-keycol-2.tsv
new file mode 100644
--- /dev/null
+++ b/tests/golden/slide-keycol-2.tsv
@@ -0,0 +1,44 @@
+Region	Rep	OrderDate	Item	Units	Unit_Cost	Total
+East	Jones	2016-01-06	Pencil	95	1.99	189.05
+Central	Kivell	2016-01-23	Binder	50	19.99	999.50
+Central	Jardine	2016-02-09	Pencil	36	4.99	179.64
+Central	Gill	2016-02-26	Pen	27	19.99	539.73
+West	Sorvino	2016-03-15	Pencil	56	2.99	167.44
+East	Jones	2016-04-01	Binder	60	4.99	299.40
+Central	Andrews	2016-04-18	Pencil	75	1.99	149.25
+Central	Jardine	2016-05-05	Pencil	90	4.99	449.10
+West	Thompson	2016-05-22	Pencil	32	1.99	63.68
+East	Jones	2016-06-08	Binder	60	8.99	539.40
+Central	Morgan	2016-06-25	Pencil	90	4.99	449.10
+East	Howard	2016-07-12	Binder	29	1.99	57.71
+East	Parent	2016-07-29	Binder	81	19.99	1619.19
+East	Jones	2016-08-15	Pencil	35	4.99	174.65
+Central	Smith	2016-09-01	Desk	2	125.00	250.00
+East	Jones	2016-09-18	Pen Set	16	15.99	255.84
+Central	Morgan	2016-10-05	Binder	28	8.99	251.72
+East	Jones	2016-10-22	Pen	64	8.99	575.36
+East	Parent	2016-11-08	Pen	15	19.99	299.85
+Central	Kivell	2016-11-25	Pen Set	96	4.99	479.04
+Central	Smith	2016-12-12	Pencil	67	1.29	86.43
+East	Parent	2016-12-29	Pen Set	74	15.99	1183.26
+Central	Gill	2017-01-15	Binder	46	8.99	413.54
+Central	Smith	2017-02-01	Binder	87	15.00	1305.00
+East	Jones	2017-02-18	Binder	4	4.99	19.96
+West	Sorvino	2017-03-07	Binder	7	19.99	139.93
+Central	Jardine	2017-03-24	Pen Set	50	4.99	249.50
+Central	Andrews	2017-04-10	Pencil	66	1.99	131.34
+East	Howard	2017-04-27	Pen	96	4.99	479.04
+Central	Gill	2017-05-14	Pencil	53	1.29	68.37
+Central	Gill	2017-05-31	Binder	80	8.99	719.20
+Central	Kivell	2017-06-17	Desk	5	125.00	625.00
+East	Jones	2017-07-04	Pen Set	62	4.99	309.38
+Central	Morgan	2017-07-21	Pen Set	55	12.49	686.95
+Central	Kivell	2017-08-07	Pen Set	42	23.95	1005.90
+West	Sorvino	2017-08-24	Desk	3	275.00	825.00
+Central	Gill	2017-09-10	Pencil	7	1.29	9.03
+West	Sorvino	2017-09-27	Pen	76	1.99	151.24
+West	Thompson	2017-10-14	Binder	57	19.99	1139.43
+Central	Andrews	2017-10-31	Pencil	14	1.29	18.06
+Central	Jardine	2017-11-17	Binder	11	4.99	54.89
+Central	Jardine	2017-12-04	Binder	94	19.99	1879.06
+Central	Andrews	2017-12-21	Binder	28	4.99	139.72
diff --git a/tests/golden/slide-keycol-3.tsv b/tests/golden/slide-keycol-3.tsv
new file mode 100644
--- /dev/null
+++ b/tests/golden/slide-keycol-3.tsv
@@ -0,0 +1,44 @@
+OrderDate	Rep	Region	Item	Units	Unit_Cost	Total
+2016-01-06	Jones	East	Pencil	95	1.99	189.05
+2016-01-23	Kivell	Central	Binder	50	19.99	999.50
+2016-02-09	Jardine	Central	Pencil	36	4.99	179.64
+2016-02-26	Gill	Central	Pen	27	19.99	539.73
+2016-03-15	Sorvino	West	Pencil	56	2.99	167.44
+2016-04-01	Jones	East	Binder	60	4.99	299.40
+2016-04-18	Andrews	Central	Pencil	75	1.99	149.25
+2016-05-05	Jardine	Central	Pencil	90	4.99	449.10
+2016-05-22	Thompson	West	Pencil	32	1.99	63.68
+2016-06-08	Jones	East	Binder	60	8.99	539.40
+2016-06-25	Morgan	Central	Pencil	90	4.99	449.10
+2016-07-12	Howard	East	Binder	29	1.99	57.71
+2016-07-29	Parent	East	Binder	81	19.99	1619.19
+2016-08-15	Jones	East	Pencil	35	4.99	174.65
+2016-09-01	Smith	Central	Desk	2	125.00	250.00
+2016-09-18	Jones	East	Pen Set	16	15.99	255.84
+2016-10-05	Morgan	Central	Binder	28	8.99	251.72
+2016-10-22	Jones	East	Pen	64	8.99	575.36
+2016-11-08	Parent	East	Pen	15	19.99	299.85
+2016-11-25	Kivell	Central	Pen Set	96	4.99	479.04
+2016-12-12	Smith	Central	Pencil	67	1.29	86.43
+2016-12-29	Parent	East	Pen Set	74	15.99	1183.26
+2017-01-15	Gill	Central	Binder	46	8.99	413.54
+2017-02-01	Smith	Central	Binder	87	15.00	1305.00
+2017-02-18	Jones	East	Binder	4	4.99	19.96
+2017-03-07	Sorvino	West	Binder	7	19.99	139.93
+2017-03-24	Jardine	Central	Pen Set	50	4.99	249.50
+2017-04-10	Andrews	Central	Pencil	66	1.99	131.34
+2017-04-27	Howard	East	Pen	96	4.99	479.04
+2017-05-14	Gill	Central	Pencil	53	1.29	68.37
+2017-05-31	Gill	Central	Binder	80	8.99	719.20
+2017-06-17	Kivell	Central	Desk	5	125.00	625.00
+2017-07-04	Jones	East	Pen Set	62	4.99	309.38
+2017-07-21	Morgan	Central	Pen Set	55	12.49	686.95
+2017-08-07	Kivell	Central	Pen Set	42	23.95	1005.90
+2017-08-24	Sorvino	West	Desk	3	275.00	825.00
+2017-09-10	Gill	Central	Pencil	7	1.29	9.03
+2017-09-27	Sorvino	West	Pen	76	1.99	151.24
+2017-10-14	Thompson	West	Binder	57	19.99	1139.43
+2017-10-31	Andrews	Central	Pencil	14	1.29	18.06
+2017-11-17	Jardine	Central	Binder	11	4.99	54.89
+2017-12-04	Jardine	Central	Binder	94	19.99	1879.06
+2017-12-21	Andrews	Central	Binder	28	4.99	139.72
diff --git a/tests/golden/slide-keycol-4.tsv b/tests/golden/slide-keycol-4.tsv
new file mode 100644
--- /dev/null
+++ b/tests/golden/slide-keycol-4.tsv
@@ -0,0 +1,44 @@
+Region	OrderDate	Rep	Item	Units	Unit_Cost	Total
+East	2016-01-06	Jones	Pencil	95	1.99	189.05
+Central	2016-01-23	Kivell	Binder	50	19.99	999.50
+Central	2016-02-09	Jardine	Pencil	36	4.99	179.64
+Central	2016-02-26	Gill	Pen	27	19.99	539.73
+West	2016-03-15	Sorvino	Pencil	56	2.99	167.44
+East	2016-04-01	Jones	Binder	60	4.99	299.40
+Central	2016-04-18	Andrews	Pencil	75	1.99	149.25
+Central	2016-05-05	Jardine	Pencil	90	4.99	449.10
+West	2016-05-22	Thompson	Pencil	32	1.99	63.68
+East	2016-06-08	Jones	Binder	60	8.99	539.40
+Central	2016-06-25	Morgan	Pencil	90	4.99	449.10
+East	2016-07-12	Howard	Binder	29	1.99	57.71
+East	2016-07-29	Parent	Binder	81	19.99	1619.19
+East	2016-08-15	Jones	Pencil	35	4.99	174.65
+Central	2016-09-01	Smith	Desk	2	125.00	250.00
+East	2016-09-18	Jones	Pen Set	16	15.99	255.84
+Central	2016-10-05	Morgan	Binder	28	8.99	251.72
+East	2016-10-22	Jones	Pen	64	8.99	575.36
+East	2016-11-08	Parent	Pen	15	19.99	299.85
+Central	2016-11-25	Kivell	Pen Set	96	4.99	479.04
+Central	2016-12-12	Smith	Pencil	67	1.29	86.43
+East	2016-12-29	Parent	Pen Set	74	15.99	1183.26
+Central	2017-01-15	Gill	Binder	46	8.99	413.54
+Central	2017-02-01	Smith	Binder	87	15.00	1305.00
+East	2017-02-18	Jones	Binder	4	4.99	19.96
+West	2017-03-07	Sorvino	Binder	7	19.99	139.93
+Central	2017-03-24	Jardine	Pen Set	50	4.99	249.50
+Central	2017-04-10	Andrews	Pencil	66	1.99	131.34
+East	2017-04-27	Howard	Pen	96	4.99	479.04
+Central	2017-05-14	Gill	Pencil	53	1.29	68.37
+Central	2017-05-31	Gill	Binder	80	8.99	719.20
+Central	2017-06-17	Kivell	Desk	5	125.00	625.00
+East	2017-07-04	Jones	Pen Set	62	4.99	309.38
+Central	2017-07-21	Morgan	Pen Set	55	12.49	686.95
+Central	2017-08-07	Kivell	Pen Set	42	23.95	1005.90
+West	2017-08-24	Sorvino	Desk	3	275.00	825.00
+Central	2017-09-10	Gill	Pencil	7	1.29	9.03
+West	2017-09-27	Sorvino	Pen	76	1.99	151.24
+West	2017-10-14	Thompson	Binder	57	19.99	1139.43
+Central	2017-10-31	Andrews	Pencil	14	1.29	18.06
+Central	2017-11-17	Jardine	Binder	11	4.99	54.89
+Central	2017-12-04	Jardine	Binder	94	19.99	1879.06
+Central	2017-12-21	Andrews	Binder	28	4.99	139.72
diff --git a/tests/slide-keycol-1.vd b/tests/slide-keycol-1.vd
new file mode 100644
--- /dev/null
+++ b/tests/slide-keycol-1.vd
@@ -0,0 +1,6 @@
+sheet	col	row	longname	input	keystrokes	comment
+			open-file	sample_data/sample.tsv	o	
+sample	OrderDate		key-col		!	toggle current column as a key column
+sample	Region		key-col		!	toggle current column as a key column
+sample	Rep		key-col		!	toggle current column as a key column
+sample	Rep		slide-leftmost		gH	slide current column all the way to the left of sheet
diff --git a/tests/slide-keycol-2.vd b/tests/slide-keycol-2.vd
new file mode 100644
--- /dev/null
+++ b/tests/slide-keycol-2.vd
@@ -0,0 +1,6 @@
+sheet	col	row	longname	input	keystrokes	comment
+			open-file	sample_data/sample.tsv	o	
+sample	OrderDate		key-col		!	toggle current column as a key column
+sample	Region		key-col		!	toggle current column as a key column
+sample	Rep		key-col		!	toggle current column as a key column
+sample	OrderDate		slide-rightmost		gL	slide current column all the way to the right of sheet
diff --git a/tests/slide-keycol-3.vd b/tests/slide-keycol-3.vd
new file mode 100644
--- /dev/null
+++ b/tests/slide-keycol-3.vd
@@ -0,0 +1,6 @@
+sheet	col	row	longname	input	keystrokes	comment
+			open-file	sample_data/sample.tsv	o	
+sample	OrderDate		key-col		!	toggle current column as a key column
+sample	Region		key-col		!	toggle current column as a key column
+sample	Rep		key-col		!	toggle current column as a key column
+sample	Rep		slide-left		H	slide current column left
diff --git a/tests/slide-keycol-4.vd b/tests/slide-keycol-4.vd
new file mode 100644
--- /dev/null
+++ b/tests/slide-keycol-4.vd
@@ -0,0 +1,6 @@
+sheet	col	row	longname	input	keystrokes	comment
+			open-file	sample_data/sample.tsv	o	
+sample	OrderDate		key-col		!	toggle current column as a key column
+sample	Region		key-col		!	toggle current column as a key column
+sample	Rep		key-col		!	toggle current column as a key column
+sample	OrderDate		slide-right		L	slide current column right