@lvce-editor/file-search-worker 5.8.0 → 5.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1003,7 +1003,7 @@ const create = (uid, uri, listItemHeight, x, y, width, height, platform, args, w
1003
1003
  width: 600,
1004
1004
  ...create$1({
1005
1005
  itemHeight: listItemHeight,
1006
- headerHeight: 30,
1006
+ headerHeight: 38,
1007
1007
  minimumSliderSize: minimumSliderSize
1008
1008
  }),
1009
1009
  inputSource: User,
@@ -1083,30 +1083,29 @@ const focusPick$1 = async pick => {
1083
1083
  await setColorTheme(/* colorThemeId */label);
1084
1084
  };
1085
1085
 
1086
- const CommandPalette = 'quickPick://commandPalette';
1087
- const Commands = 'quickPick://commands';
1088
- const File$2 = 'quickPick://file';
1089
- const EveryThing = 'quickPick://everything';
1090
- const Recent = 'quickPick://recent';
1091
- const ColorTheme = 'quickPick://color-theme';
1092
- const Symbol$1 = 'quickPick://symbol';
1093
- const View$1 = 'quickPick://view';
1094
- const WorkspaceSymbol$1 = 'quickPick://workspace-symbol';
1095
- const Custom = 'quickPick://custom';
1096
- const GoToLine$1 = 'quickPick://go-to-line';
1097
- const Noop = 'quickPick://noop';
1086
+ const ColorTheme$1 = 0;
1087
+ const Commands$1 = 1;
1088
+ const Custom = 2;
1089
+ const File$2 = 3;
1090
+ const GoToLine$2 = 4;
1091
+ const Help$2 = 5;
1092
+ const Recent$1 = 6;
1093
+ const Symbol$2 = 7;
1094
+ const View$3 = 8;
1095
+ const WorkspaceSymbol$2 = 9;
1096
+ const EveryThing$1 = 100;
1098
1097
 
1099
1098
  const noop$2 = async () => {};
1100
- const getFn$2 = id => {
1099
+ const getFn$3 = id => {
1101
1100
  switch (id) {
1102
- case ColorTheme:
1101
+ case ColorTheme$1:
1103
1102
  return focusPick$1;
1104
1103
  default:
1105
1104
  return noop$2;
1106
1105
  }
1107
1106
  };
1108
1107
  const focusPick = (id, pick) => {
1109
- const fn = getFn$2(id);
1108
+ const fn = getFn$3(id);
1110
1109
  return fn(pick);
1111
1110
  };
1112
1111
 
@@ -1191,14 +1190,14 @@ const getQuickPickFileIcons = async (items, fileIconCache) => {
1191
1190
 
1192
1191
  const focusIndex = async (state, index) => {
1193
1192
  const {
1194
- uri,
1193
+ providerId,
1195
1194
  maxVisibleItems,
1196
1195
  items,
1197
1196
  minLineY,
1198
1197
  maxLineY,
1199
1198
  fileIconCache
1200
1199
  } = state;
1201
- await focusPick(uri, items[index]);
1200
+ await focusPick(providerId, items[index]);
1202
1201
  if (index < minLineY + 1) {
1203
1202
  const minLineY = index;
1204
1203
  const maxLineY = Math.min(index + maxVisibleItems, items.length - 1);
@@ -1662,27 +1661,28 @@ const filterQuickPickItems = (items, value) => {
1662
1661
  };
1663
1662
 
1664
1663
  const Command = '>';
1665
- const Symbol = '@';
1666
- const WorkspaceSymbol = '#';
1667
- const GoToLine = ':';
1668
- const View = 'view ';
1664
+ const Symbol$1 = '@';
1665
+ const WorkspaceSymbol$1 = '#';
1666
+ const GoToLine$1 = ':';
1667
+ const View$2 = 'view ';
1669
1668
  const None$1 = '';
1669
+ const Help$1 = '?';
1670
1670
 
1671
1671
  const getQuickPickPrefix = value => {
1672
1672
  if (value.startsWith(Command)) {
1673
1673
  return Command;
1674
1674
  }
1675
- if (value.startsWith(Symbol)) {
1676
- return Symbol;
1675
+ if (value.startsWith(Symbol$1)) {
1676
+ return Symbol$1;
1677
1677
  }
1678
- if (value.startsWith(WorkspaceSymbol)) {
1679
- return WorkspaceSymbol;
1678
+ if (value.startsWith(WorkspaceSymbol$1)) {
1679
+ return WorkspaceSymbol$1;
1680
1680
  }
1681
- if (value.startsWith(GoToLine)) {
1682
- return GoToLine;
1681
+ if (value.startsWith(GoToLine$1)) {
1682
+ return GoToLine$1;
1683
1683
  }
1684
- if (value.startsWith(View)) {
1685
- return View;
1684
+ if (value.startsWith(View$2)) {
1685
+ return View$2;
1686
1686
  }
1687
1687
  return None$1;
1688
1688
  };
@@ -1695,359 +1695,274 @@ const getFilterValueEverything = value => {
1695
1695
  const prefixLength = prefix.length;
1696
1696
  return value.slice(prefixLength).trim();
1697
1697
  };
1698
- const getFn$1 = id => {
1698
+ const getFn$2 = id => {
1699
1699
  switch (id) {
1700
- case EveryThing:
1700
+ case EveryThing$1:
1701
1701
  return getFilterValueEverything;
1702
1702
  default:
1703
1703
  return noop$1;
1704
1704
  }
1705
1705
  };
1706
1706
  const getFilterValue = (id, value) => {
1707
- const fn = getFn$1(id);
1707
+ const fn = getFn$2(id);
1708
1708
  const filterValue = fn(value);
1709
1709
  return filterValue;
1710
1710
  };
1711
1711
 
1712
- const select = Object.create(null);
1713
- const getPick$1 = Object.create(null);
1714
- const registerSelect = modules => {
1715
- Object.assign(select, modules);
1712
+ const getColorThemeNames = async () => {
1713
+ return invoke$1(/* Ajax.getJson */'ColorTheme.getColorThemeNames');
1716
1714
  };
1717
- const registerGetPick = modules => {
1718
- Object.assign(getPick$1, modules);
1715
+
1716
+ const toProtoVisibleItem$2 = name => {
1717
+ const pick = {
1718
+ label: name,
1719
+ description: '',
1720
+ fileIcon: '',
1721
+ icon: '',
1722
+ matches: [],
1723
+ direntType: 0,
1724
+ uri: ''
1725
+ };
1726
+ return pick;
1719
1727
  };
1720
- const getPicks$c = id => {
1721
- const fn = getPick$1[id];
1722
- return fn;
1728
+ const getPicks$c = async searchValue => {
1729
+ const colorThemeNames = await getColorThemeNames();
1730
+ const picks = colorThemeNames.map(toProtoVisibleItem$2);
1731
+ return picks;
1723
1732
  };
1724
- const getSelect = id => {
1725
- const fn = select[id];
1726
- return fn;
1733
+
1734
+ const handleError = async (error, notify = true, prefix = '') => {
1735
+ console.error(error);
1736
+ };
1737
+ const showErrorDialog = async error => {
1738
+ const code = error.code;
1739
+ const message = error.message;
1740
+ const stack = error.stack;
1741
+ const name = error.name;
1742
+ const errorInfo = {
1743
+ code,
1744
+ message,
1745
+ stack,
1746
+ name
1747
+ };
1748
+ await invoke$1('ErrorHandling.showErrorDialog', errorInfo);
1749
+ };
1750
+ const warn = (...args) => {
1751
+ console.warn(...args);
1727
1752
  };
1728
1753
 
1729
- const getPicks$b = (id, searchValue) => {
1730
- const fn = getPicks$c(id);
1731
- return fn(searchValue);
1754
+ const state$2 = {
1755
+ menuEntries: []
1756
+ };
1757
+ const getAll = () => {
1758
+ return state$2.menuEntries;
1759
+ };
1760
+ const add = menuEntries => {
1761
+ state$2.menuEntries = [...state$2.menuEntries, ...menuEntries];
1732
1762
  };
1733
1763
 
1734
- // TODO when user types letters -> no need to query provider again -> just filter existing results
1735
- const setValue = async (state, newValue) => {
1736
- const {
1737
- value,
1738
- uri,
1739
- minLineY,
1740
- maxLineY,
1741
- fileIconCache
1742
- } = state;
1743
- if (value === newValue) {
1744
- return state;
1764
+ // TODO combine Ajax with cache (specify strategy: cacheFirst, networkFirst)
1765
+ const getBuiltinPicks = async () => {
1766
+ const builtinPicks = getAll();
1767
+ return builtinPicks;
1768
+ };
1769
+ const prefixIdWithExt = item => {
1770
+ if (!item.label) {
1771
+ warn('[QuickPick] item has missing label', item);
1772
+ }
1773
+ if (!item.id) {
1774
+ warn('[QuickPick] item has missing id', item);
1745
1775
  }
1746
- const newPicks = await getPicks$b(uri, newValue);
1747
- const filterValue = getFilterValue(uri, newValue);
1748
- const items = filterQuickPickItems(newPicks, filterValue);
1749
- const focusedIndex = items.length === 0 ? -1 : 0;
1750
- const sliced = items.slice(minLineY, maxLineY);
1751
- const {
1752
- newFileIconCache,
1753
- icons
1754
- } = await getQuickPickFileIcons(sliced, fileIconCache);
1755
1776
  return {
1756
- ...state,
1757
- picks: newPicks,
1758
- items,
1759
- focusedIndex,
1760
- inputSource: Script,
1761
- value: newValue,
1762
- icons,
1763
- fileIconCache: newFileIconCache
1777
+ ...item,
1778
+ id: `ext.${item.id}`,
1779
+ label: item.label || item.id
1764
1780
  };
1765
1781
  };
1766
-
1767
- // TODO when user types letters -> no need to query provider again -> just filter existing results
1768
- const handleInput = async (state, newValue, cursorOffset, inputSource = Script) => {
1769
- if (state.value === newValue) {
1770
- return state;
1782
+ const getExtensionPicks = async () => {
1783
+ try {
1784
+ // TODO don't call this every time
1785
+ const extensionPicks = await invoke$1('ExtensionHost.getCommands');
1786
+ if (!extensionPicks) {
1787
+ return [];
1788
+ }
1789
+ const mappedPicks = extensionPicks.map(prefixIdWithExt);
1790
+ return mappedPicks;
1791
+ } catch (error) {
1792
+ console.error(`Failed to get extension picks: ${error}`);
1793
+ return [];
1771
1794
  }
1772
- const newState = await setValue(state, newValue);
1773
- return {
1774
- ...newState,
1775
- cursorOffset,
1776
- inputSource
1795
+ };
1796
+ const toProtoVisibleItem$1 = item => {
1797
+ const pick = {
1798
+ label: item.label,
1799
+ description: '',
1800
+ fileIcon: '',
1801
+ icon: '',
1802
+ matches: [],
1803
+ direntType: 0,
1804
+ uri: ''
1777
1805
  };
1806
+ // @ts-ignore
1807
+ pick.id = item.id;
1808
+ return pick;
1778
1809
  };
1779
-
1780
- const handleBeforeInput = (state, inputType, data, selectionStart, selectionEnd) => {
1781
- string(inputType);
1782
- number(selectionStart);
1783
- number(selectionEnd);
1784
- const {
1785
- value
1786
- } = state;
1787
- const {
1788
- newValue,
1789
- cursorOffset
1790
- } = getNewValue(value, inputType, data, selectionStart, selectionEnd);
1791
- return handleInput(state, newValue, cursorOffset, User);
1810
+ const getPicks$b = async () => {
1811
+ // TODO get picks in parallel
1812
+ const builtinPicks = await getBuiltinPicks();
1813
+ const extensionPicks = await getExtensionPicks();
1814
+ const allPicks = [...builtinPicks, ...extensionPicks];
1815
+ const converted = allPicks.map(toProtoVisibleItem$1);
1816
+ return converted;
1792
1817
  };
1793
1818
 
1794
- const handleBlur = async state => {
1795
- // TODO fix virtual dom diffing so that input isn't destroyed and loses focus when rerendering
1796
- // await CloseWidget.closeWidget(state.uid)
1797
- return state;
1819
+ const state$1 = {
1820
+ args: []
1798
1821
  };
1799
1822
 
1800
- const getPick = (items, index) => {
1801
- array(items);
1802
- number(index);
1803
- // if (index < state.recentPicks.length) {
1804
- // return state.recentPicks[index]
1805
- // }
1806
- // index -= state.recentPicks.length
1807
- if (index < items.length) {
1808
- return items[index];
1809
- }
1810
- console.warn('no pick matching index', index);
1811
- return undefined;
1823
+ const getPicks$a = async searchValue => {
1824
+ const items = state$1.args[1] || [];
1825
+ return items;
1812
1826
  };
1813
1827
 
1814
- const Hide = 'hide';
1815
- const KeepOpen = '';
1816
-
1817
- const selectIndex = async (state, index, button = /* left */0) => {
1818
- const {
1819
- minLineY,
1820
- uri,
1821
- items
1822
- } = state;
1823
- const actualIndex = index + minLineY;
1824
- const pick = getPick(items, actualIndex);
1825
- if (!pick) {
1826
- return state;
1827
- }
1828
- const fn = getSelect(uri);
1829
- const selectPickResult = await fn(pick);
1830
- object(selectPickResult);
1831
- string(selectPickResult.command);
1832
- const {
1833
- command
1834
- } = selectPickResult;
1835
- switch (command) {
1836
- case Hide:
1837
- await closeWidget(state.uid);
1838
- return state;
1839
- default:
1840
- return state;
1841
- }
1828
+ const emptyMatches = [];
1842
1829
 
1843
- // TODO recent picks should be per provider
1844
- // if (!state.recentPickIds.has(pick.id)) {
1845
- // state.recentPicks.unshift(pick)
1846
- // state.recentPickIds.add(pick.id)
1847
- // }
1848
- // if (state.recentPicks.length > RECENT_PICKS_MAX_SIZE) {
1849
- // const last = state.recentPicks.pop()
1850
- // state.recentPickIds.delete(last.id)
1851
- // }
1830
+ const getWorkspacePath = async () => {
1831
+ return invoke$1('Workspace.getPath');
1852
1832
  };
1853
1833
 
1854
- const handleClickAt = (state, x, y) => {
1855
- const {
1856
- top,
1857
- headerHeight,
1858
- itemHeight
1859
- } = state;
1860
- const relativeY = y - top - headerHeight;
1861
- const index = Math.floor(relativeY / itemHeight);
1862
- return selectIndex(state, index);
1834
+ const RE_PROTOCOL = /^([a-z-]+):\/\//;
1835
+ const getProtocol = uri => {
1836
+ const protocolMatch = uri.match(RE_PROTOCOL);
1837
+ if (protocolMatch) {
1838
+ return protocolMatch[1];
1839
+ }
1840
+ return '';
1863
1841
  };
1864
1842
 
1865
- const setFocus = async focusKey => {
1866
- await invoke$1('Focus.setFocus', focusKey);
1843
+ const state = Object.create(null);
1844
+ const register = modules => {
1845
+ Object.assign(state, modules);
1867
1846
  };
1868
-
1869
- const handleFocus = async state => {
1870
- // TODO fix virtual dom diffing so that input isn't destroyed and loses focus when rerendering
1871
- await setFocus(FocusQuickPickInput);
1872
- // await CloseWidget.closeWidget(state.uid)
1873
- return state;
1847
+ const getFn$1 = protocol => {
1848
+ return state[protocol];
1874
1849
  };
1875
1850
 
1876
- const getDefaultValue = uri => {
1877
- switch (uri) {
1878
- case 'quickPick://everything':
1879
- return '>';
1880
- default:
1881
- return '';
1882
- }
1851
+ const searchFile$5 = async (path, value, prepare, assetDir) => {
1852
+ const protocol = getProtocol(path);
1853
+ // TODO call different providers depending on protocol
1854
+ const fn = getFn$1(protocol);
1855
+ const result = await fn(path, value, prepare, assetDir);
1856
+ return result;
1883
1857
  };
1884
1858
 
1885
- const state$3 = {
1886
- args: []
1859
+ // TODO this should be in FileSystem module
1860
+ const pathBaseName = path => {
1861
+ return path.slice(path.lastIndexOf('/') + 1);
1887
1862
  };
1888
1863
 
1889
- const noop = args => {};
1890
- const setArgsCustom = args => {
1891
- state$3.args = args;
1892
- };
1893
- const getFn = id => {
1894
- switch (id) {
1895
- case Custom:
1896
- return setArgsCustom;
1897
- default:
1898
- return noop;
1864
+ // TODO this should be in FileSystem module
1865
+ const pathDirName = path => {
1866
+ const pathSeparator = '/';
1867
+ const index = path.lastIndexOf(pathSeparator);
1868
+ if (index === -1) {
1869
+ return '';
1899
1870
  }
1900
- };
1901
- const setArgs = (id, args) => {
1902
- const fn = getFn(id);
1903
- return fn(args);
1904
- };
1905
-
1906
- const loadContent = async state => {
1907
- const {
1908
- uri,
1909
- args,
1910
- fileIconCache
1911
- } = state;
1912
- const value = getDefaultValue(uri);
1913
- setArgs(uri, args);
1914
- const newPicks = await getPicks$b(uri, value);
1915
- array(newPicks);
1916
- const filterValue = getFilterValue(uri, value);
1917
- const items = filterQuickPickItems(newPicks, filterValue);
1918
- const minLineY = 0;
1919
- const maxLineY = Math.min(minLineY + state.maxVisibleItems, newPicks.length);
1920
- const sliced = newPicks.slice(minLineY, maxLineY);
1921
- const {
1922
- newFileIconCache,
1923
- icons
1924
- } = await getQuickPickFileIcons(sliced, fileIconCache);
1925
- return {
1926
- ...state,
1927
- picks: newPicks,
1928
- items,
1929
- focusedIndex: 0,
1930
- state: Finished,
1931
- minLineY,
1932
- maxLineY,
1933
- value,
1934
- cursorOffset: value.length,
1935
- inputSource: Script,
1936
- focused: true,
1937
- fileIconCache: newFileIconCache,
1938
- icons
1939
- };
1940
- };
1941
-
1942
- const state$2 = {
1943
- menuEntries: []
1944
- };
1945
- const getAll = () => {
1946
- return state$2.menuEntries;
1947
- };
1948
- const add = menuEntries => {
1949
- state$2.menuEntries = [...state$2.menuEntries, ...menuEntries];
1950
- };
1951
-
1952
- const getVisible$1 = (items, minLineY, maxLineY, icons) => {
1953
- const range = items.slice(minLineY, maxLineY);
1954
- const protoVisibleItems = range.map((item, index) => {
1955
- return {
1956
- ...item,
1957
- fileIcon: icons[index]
1958
- };
1959
- });
1960
- return protoVisibleItems;
1871
+ return path.slice(0, index);
1961
1872
  };
1962
1873
 
1963
- const getVisible = (setSize, protoVisibleItems, minLineY, focusedIndex) => {
1964
- const visibleItems = protoVisibleItems.map((visibleItem, i) => {
1965
- return {
1966
- ...visibleItem,
1967
- posInSet: minLineY + i + 1,
1968
- setSize,
1969
- isActive: i === focusedIndex
1970
- };
1971
- });
1972
- return visibleItems;
1874
+ const searchFile$4 = async (path, value) => {
1875
+ const prepare = true;
1876
+ const files = await searchFile$5(/* path */path, /* searchTerm */value, prepare, '');
1877
+ return files;
1973
1878
  };
1974
-
1975
- const createQuickPickViewModel = (oldState, newState) => {
1976
- const protoVisibleItems = getVisible$1(newState.items, newState.minLineY, newState.maxLineY, newState.icons);
1977
- const visibleItems = getVisible(newState.items.length, protoVisibleItems, newState.minLineY, newState.focusedIndex);
1978
- const oldFocusedIndex = oldState.focusedIndex - oldState.minLineY;
1979
- const newFocusedIndex = newState.focusedIndex - newState.minLineY;
1980
- const maxLineY = Math.min(newState.maxLineY, newState.items.length);
1981
- const itemCount = maxLineY - newState.minLineY;
1982
- const height = itemCount * newState.itemHeight;
1879
+ const convertToPick = uri => {
1880
+ const baseName = pathBaseName(uri);
1881
+ const dirName = pathDirName(uri);
1983
1882
  return {
1984
- visibleItems,
1985
- value: newState.value,
1986
- cursorOffset: newState.cursorOffset,
1987
- focused: newState.focused,
1988
- height,
1989
- oldFocusedIndex,
1990
- newFocusedIndex,
1991
- uid: newState.uid
1883
+ description: dirName,
1884
+ direntType: File$1,
1885
+ fileIcon: '',
1886
+ icon: '',
1887
+ label: baseName,
1888
+ matches: emptyMatches,
1889
+ uri
1992
1890
  };
1993
1891
  };
1994
1892
 
1995
- const SetCursorOffset = 'setCursorOffset';
1996
- const SetFocusedIndex = 'setFocusedIndex';
1997
- const SetItemsHeight = 'setItemsHeight';
1998
- const SetValue = 'setValue';
1999
-
2000
- const renderCursorOffset = newState => {
2001
- return ['Viewlet.send', newState.uid, /* method */SetCursorOffset, /* cursorOffset */newState.cursorOffset];
2002
- };
2003
-
2004
- const QuickPickInput = 'QuickPickInput';
2005
-
2006
- const renderFocus = newState => {
2007
- return ['Viewlet.focusElementByName', QuickPickInput];
2008
- };
2009
-
2010
- const renderFocusedIndex = newState => {
2011
- return ['Viewlet.send', newState.uid, /* method */SetFocusedIndex, /* oldFocusedIndex */newState.oldFocusedIndex, /* newFocusedIndex */newState.newFocusedIndex];
2012
- };
1893
+ // TODO handle files differently
1894
+ // e.g. when there are many files, don't need
1895
+ // to compute the fileIcon for all files
2013
1896
 
2014
- const renderHeight = newState => {
2015
- if (newState.height === 0) {
2016
- return ['Viewlet.send', newState.uid, /* method */SetItemsHeight, /* height */20];
1897
+ const getPicks$9 = async searchValue => {
1898
+ // TODO cache workspace path
1899
+ const workspace = await getWorkspacePath();
1900
+ if (!workspace) {
1901
+ return [];
2017
1902
  }
2018
- return ['Viewlet.send', newState.uid, /* method */SetItemsHeight, /* height */newState.height];
1903
+ const files = await searchFile$4(workspace, searchValue);
1904
+ const picks = files.map(convertToPick);
1905
+ return picks;
2019
1906
  };
2020
1907
 
2021
- const ComboBox = 'combobox';
2022
- const ListBox = 'listbox';
2023
- const None = 'none';
2024
- const Option = 'option';
2025
-
2026
- const FileIcon = 'FileIcon';
2027
- const InputBox = 'InputBox';
2028
- const Label = 'Label';
2029
- const QuickPick$1 = 'QuickPick';
2030
- const QuickPickHeader = 'QuickPickHeader';
2031
- const QuickPickHighlight = 'QuickPickHighlight';
2032
- const QuickPickItem = 'QuickPickItem';
2033
- const QuickPickItemActive$1 = 'QuickPickItemActive';
2034
- const QuickPickItemDescription = 'QuickPickItemDescription';
2035
- const QuickPickItemLabel = 'QuickPickItemLabel';
2036
- const QuickPickMaskIcon = 'QuickPickMaskIcon';
2037
- const QuickPickItems$1 = 'QuickPickItems';
2038
- const MaskIcon = 'MaskIcon';
2039
- const Viewlet = 'Viewlet';
2040
-
2041
- const HandleBeforeInput = 'handleBeforeInput';
2042
- const HandleBlur = 'handleBlur';
2043
- const HandleFocus = 'handleFocus';
2044
- const HandleInput = 'handleInput';
2045
- const HandlePointerDown = 'handlePointerDown';
2046
- const HandleWheel = 'handleWheel';
1908
+ const getPicks$8 = async () => {
1909
+ const picks = [{
1910
+ label: '1',
1911
+ description: '',
1912
+ icon: '',
1913
+ fileIcon: '',
1914
+ matches: [],
1915
+ direntType: None$2,
1916
+ uri: ''
1917
+ }, {
1918
+ label: '2',
1919
+ description: '',
1920
+ icon: '',
1921
+ fileIcon: '',
1922
+ matches: [],
1923
+ direntType: None$2,
1924
+ uri: ''
1925
+ }, {
1926
+ label: '3',
1927
+ description: '',
1928
+ icon: '',
1929
+ fileIcon: '',
1930
+ matches: [],
1931
+ direntType: None$2,
1932
+ uri: ''
1933
+ }, {
1934
+ label: '4',
1935
+ description: '',
1936
+ icon: '',
1937
+ fileIcon: '',
1938
+ matches: [],
1939
+ direntType: None$2,
1940
+ uri: ''
1941
+ }, {
1942
+ label: '5',
1943
+ description: '',
1944
+ icon: '',
1945
+ fileIcon: '',
1946
+ matches: [],
1947
+ direntType: None$2,
1948
+ uri: ''
1949
+ }, {
1950
+ label: '6',
1951
+ description: '',
1952
+ icon: '',
1953
+ fileIcon: '',
1954
+ matches: [],
1955
+ direntType: None$2,
1956
+ uri: ''
1957
+ }];
1958
+ return picks;
1959
+ };
2047
1960
 
2048
- const QuickPick = 'QuickPick';
2049
- const QuickPickItems = 'QuickPickItems';
2050
- const QuickPickItemActive = 'QuickPickItemActive';
1961
+ const DotDotDot = '...';
1962
+ const Colon = ':';
1963
+ const Percent = '%';
1964
+ const AngleBracket = '>';
1965
+ const View$1 = 'view';
2051
1966
 
2052
1967
  const emptyObject = {};
2053
1968
  const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
@@ -2061,850 +1976,1005 @@ const i18nString = (key, placeholders = emptyObject) => {
2061
1976
  return key.replaceAll(RE_PLACEHOLDER, replacer);
2062
1977
  };
2063
1978
 
1979
+ const GoToFile = 'Go to file';
1980
+ const GoToLineColumn = 'Go to Line / Column';
1981
+ const GoToSymbolInEditor = 'Go to Symbol in Editor';
2064
1982
  const NoResults = 'No Results';
2065
- const TypeNameOfCommandToRun = 'Type the name of a command to run.';
1983
+ const OpenView = 'Open View';
2066
1984
  const QuickOpen = 'Quick open';
1985
+ const SearchForText = 'Search for text';
1986
+ const ShowAndRunCommands = 'Show And Run Commands';
1987
+ const TypeNameOfCommandToRun = 'Type the name of a command to run.';
2067
1988
 
2068
1989
  const typeNameofCommandToRun = () => {
2069
1990
  return i18nString(TypeNameOfCommandToRun);
2070
1991
  };
1992
+ const showAndRunCommands = () => {
1993
+ return i18nString(ShowAndRunCommands);
1994
+ };
1995
+ const goToFile = () => {
1996
+ return i18nString(GoToFile);
1997
+ };
2071
1998
  const noResults = () => {
2072
1999
  return i18nString(NoResults);
2073
2000
  };
2074
2001
  const quickOpen = () => {
2075
2002
  return i18nString(QuickOpen);
2076
2003
  };
2077
-
2078
- const Div = 4;
2079
- const Input = 6;
2080
- const Span = 8;
2081
- const Img = 17;
2082
-
2083
- const getQuickPickInputVirtualDom = () => {
2084
- const ariaLabel = typeNameofCommandToRun();
2085
- return {
2086
- type: Input,
2087
- className: InputBox,
2088
- spellcheck: false,
2089
- autocapitalize: 'off',
2090
- inputType: 'text',
2091
- childCount: 0,
2092
- role: ComboBox,
2093
- name: QuickPickInput,
2094
- onBeforeInput: HandleBeforeInput,
2095
- onBlur: HandleBlur,
2096
- onInput: HandleInput,
2097
- onFocus: HandleFocus,
2098
- ariaLabel: ariaLabel,
2099
- ariaAutoComplete: 'list',
2100
- ariaExpanded: true,
2101
- autocomplete: 'off'
2102
- };
2004
+ const goToLineColumn = () => {
2005
+ return i18nString(GoToLineColumn);
2006
+ };
2007
+ const goToSymbolInEditor = () => {
2008
+ return i18nString(GoToSymbolInEditor);
2009
+ };
2010
+ const searchForText = () => {
2011
+ return i18nString(SearchForText);
2012
+ };
2013
+ const openView = () => {
2014
+ return i18nString(OpenView);
2103
2015
  };
2104
2016
 
2105
- const getQuickPickHeaderVirtualDom = () => {
2017
+ const getPicks$7 = async () => {
2106
2018
  return [{
2107
- type: Div,
2108
- className: QuickPickHeader,
2109
- childCount: 1
2110
- }, getQuickPickInputVirtualDom()];
2019
+ description: goToFile(),
2020
+ direntType: None$2,
2021
+ fileIcon: '',
2022
+ icon: '',
2023
+ label: DotDotDot,
2024
+ matches: [],
2025
+ uri: ''
2026
+ }, {
2027
+ description: goToLineColumn(),
2028
+ direntType: None$2,
2029
+ fileIcon: '',
2030
+ icon: '',
2031
+ label: ':',
2032
+ matches: [],
2033
+ uri: ''
2034
+ }, {
2035
+ description: goToSymbolInEditor(),
2036
+ direntType: None$2,
2037
+ fileIcon: '',
2038
+ icon: '',
2039
+ label: Colon,
2040
+ matches: [],
2041
+ uri: ''
2042
+ }, {
2043
+ description: searchForText(),
2044
+ direntType: None$2,
2045
+ fileIcon: '',
2046
+ icon: '',
2047
+ label: Percent,
2048
+ matches: [],
2049
+ uri: ''
2050
+ }, {
2051
+ description: showAndRunCommands(),
2052
+ direntType: None$2,
2053
+ fileIcon: '',
2054
+ icon: '',
2055
+ label: AngleBracket,
2056
+ matches: [],
2057
+ uri: ''
2058
+ }, {
2059
+ description: openView(),
2060
+ direntType: None$2,
2061
+ fileIcon: '',
2062
+ icon: '',
2063
+ label: View$1,
2064
+ matches: [],
2065
+ uri: ''
2066
+ }];
2111
2067
  };
2112
2068
 
2113
- const emptyHighlightSections = [];
2114
-
2115
- const getHighlightSections = (highlights, label) => {
2116
- if (highlights.length === 0) {
2117
- return emptyHighlightSections;
2118
- }
2119
- const sections = [];
2120
- let position = 0;
2121
- for (let i = 0; i < highlights.length; i += 2) {
2122
- const highlightStart = highlights[i];
2123
- const highlightEnd = highlights[i + 1];
2124
- if (position < highlightStart) {
2125
- const beforeText = label.slice(position, highlightStart);
2126
- sections.push({
2127
- highlighted: false,
2128
- text: beforeText
2129
- });
2130
- }
2131
- const highlightText = label.slice(highlightStart, highlightEnd);
2132
- sections.push({
2133
- highlighted: true,
2134
- text: highlightText
2135
- });
2136
- position = highlightEnd;
2137
- }
2138
- if (position < label.length) {
2139
- const afterText = label.slice(position);
2140
- sections.push({
2141
- highlighted: false,
2142
- text: afterText
2143
- });
2144
- }
2145
- return sections;
2069
+ const getRecentlyOpened = () => {
2070
+ return invoke$1(/* RecentlyOpened.getRecentlyOpened */'RecentlyOpened.getRecentlyOpened');
2146
2071
  };
2147
2072
 
2148
- const mergeClassNames = (...classNames) => {
2149
- return classNames.filter(Boolean).join(' ');
2150
- };
2151
- const Text = 12;
2152
- const text = data => {
2073
+ const toProtoVisibleItem = uri => {
2153
2074
  return {
2154
- type: Text,
2155
- text: data,
2156
- childCount: 0
2075
+ label: uri,
2076
+ description: '',
2077
+ fileIcon: '',
2078
+ icon: '',
2079
+ matches: [],
2080
+ direntType: Directory,
2081
+ uri: uri
2157
2082
  };
2158
2083
  };
2084
+ const getPicks$6 = async () => {
2085
+ const recentlyOpened = await getRecentlyOpened();
2086
+ const picks = recentlyOpened.map(toProtoVisibleItem);
2087
+ return picks;
2088
+ };
2159
2089
 
2160
- const quickPickHighlight = {
2161
- type: Span,
2162
- className: QuickPickHighlight,
2163
- childCount: 1
2090
+ const getPicks$5 = async () => {
2091
+ const picks = [];
2092
+ return picks;
2164
2093
  };
2165
- const getHighlights = (highlights, label) => {
2166
- const labelDom = {
2167
- type: Div,
2168
- className: QuickPickItemLabel,
2169
- childCount: 0
2170
- };
2171
- const nodes = [labelDom];
2172
- const sections = getHighlightSections(highlights, label);
2173
- if (sections.length === 0) {
2174
- labelDom.childCount++;
2175
- nodes.push(text(label));
2176
- } else {
2177
- for (const section of sections) {
2178
- if (section.highlighted) {
2179
- labelDom.childCount++;
2180
- nodes.push(quickPickHighlight, text(section.text));
2181
- } else {
2182
- labelDom.childCount++;
2183
- nodes.push(text(section.text));
2184
- }
2185
- }
2186
- }
2187
- return nodes;
2094
+
2095
+ const getPicks$4 = async () => {
2096
+ return [];
2188
2097
  };
2189
2098
 
2190
- const addHighlights = (dom, highlights, label) => {
2191
- const domHighlights = getHighlights(highlights, label);
2192
- dom.push(...domHighlights);
2099
+ const getPicks$3 = async () => {
2100
+ const picks = [];
2101
+ return picks;
2193
2102
  };
2194
2103
 
2195
- const getFileIconVirtualDom = icon => {
2104
+ const Hide = 'hide';
2105
+ const KeepOpen = '';
2106
+
2107
+ const selectPick$9 = async pick => {
2108
+ const id = pick.label;
2109
+ await setColorTheme(/* colorThemeId */id);
2196
2110
  return {
2197
- type: Img,
2198
- className: FileIcon,
2199
- src: icon,
2200
- role: None,
2201
- childCount: 0
2111
+ command: Hide
2202
2112
  };
2203
2113
  };
2204
2114
 
2205
- const getQuickPickItemVirtualDom = visibleItem => {
2206
- const {
2207
- posInSet,
2208
- label,
2209
- setSize,
2210
- isActive,
2211
- description,
2212
- icon,
2213
- matches,
2214
- fileIcon
2215
- } = visibleItem;
2216
- const highlights = matches.slice(1);
2217
- const dom = [];
2218
- dom.push({
2219
- type: Div,
2220
- className: QuickPickItem,
2221
- role: Option,
2222
- ariaPosInSet: posInSet,
2223
- ariaSetSize: setSize,
2224
- childCount: 1
2225
- });
2226
- const parent = dom[0];
2227
- if (isActive) {
2228
- // @ts-ignore
2229
- parent.id = QuickPickItemActive;
2230
- parent.className += ' ' + QuickPickItemActive$1;
2115
+ const shouldHide = item => {
2116
+ if (item.id === 'Viewlet.openWidget' && item.args[0] === 'QuickPick') {
2117
+ return false;
2231
2118
  }
2232
- if (fileIcon) {
2233
- parent.childCount++;
2234
- dom.push(getFileIconVirtualDom(fileIcon));
2235
- } else if (icon) {
2236
- parent.childCount++;
2237
- dom.push({
2238
- type: Div,
2239
- className: mergeClassNames(QuickPickMaskIcon, MaskIcon, `MaskIcon${icon}`),
2240
- childCount: 0
2241
- });
2119
+ return true;
2120
+ };
2121
+ const selectPickBuiltin = async item => {
2122
+ const args = item.args || [];
2123
+ // TODO ids should be all numbers for efficiency -> also directly can call command
2124
+ await invoke$1(item.id, ...args);
2125
+ if (shouldHide(item)) {
2126
+ return {
2127
+ command: Hide
2128
+ };
2242
2129
  }
2243
- addHighlights(dom, highlights, label);
2244
- if (description) {
2245
- parent.childCount++;
2246
- dom.push({
2247
- type: Div,
2248
- className: QuickPickItemDescription,
2249
- childCount: 1
2250
- }, text(description));
2130
+ return {
2131
+ command: KeepOpen
2132
+ };
2133
+ };
2134
+ const selectPickExtension = async item => {
2135
+ const id = item.id.slice(4); // TODO lots of string allocation with 'ext.' find a better way to separate builtin commands from extension commands
2136
+ try {
2137
+ await invoke$1('ExtensionHost.executeCommand', id);
2138
+ } catch (error) {
2139
+ await handleError(error, false);
2140
+ await showErrorDialog(error);
2251
2141
  }
2252
- return dom;
2142
+ return {
2143
+ command: Hide
2144
+ };
2145
+ };
2146
+ const selectPick$8 = async item => {
2147
+ // @ts-ignore
2148
+ const id = item.id;
2149
+ if (id.startsWith('ext.')) {
2150
+ return selectPickExtension(item);
2151
+ }
2152
+ return selectPickBuiltin(item);
2253
2153
  };
2254
2154
 
2255
- const getQuickPickNoResultsVirtualDom = () => {
2256
- const noResults$1 = noResults();
2257
- return [{
2258
- type: Div,
2259
- className: 'QuickPickItem QuickPickItemActive QuickPickStatus',
2260
- childCount: 1
2261
- }, {
2262
- type: Div,
2263
- className: Label,
2264
- childCount: 1
2265
- }, text(noResults$1)];
2155
+ const selectPick$7 = async pick => {
2156
+ const {
2157
+ args
2158
+ } = state$1;
2159
+ const resolve = args[2];
2160
+ resolve(pick);
2161
+ return {
2162
+ command: Hide
2163
+ };
2266
2164
  };
2267
2165
 
2268
- const getQuickPickItemsVirtualDom = visibleItems => {
2269
- if (visibleItems.length === 0) {
2270
- return getQuickPickNoResultsVirtualDom();
2271
- }
2272
- const dom = visibleItems.flatMap(getQuickPickItemVirtualDom);
2273
- return dom;
2166
+ const openUri = async uri => {
2167
+ await invoke$1(/* Main.openUri */'Main.openUri', /* uri */uri);
2274
2168
  };
2275
2169
 
2276
- const getQuickPickVirtualDom = visibleItems => {
2277
- const quickOpen$1 = quickOpen();
2278
- return [{
2279
- type: Div,
2280
- className: mergeClassNames(Viewlet, QuickPick$1),
2281
- childCount: 2,
2282
- id: QuickPick,
2283
- ariaLabel: quickOpen$1
2284
- }, ...getQuickPickHeaderVirtualDom(), {
2285
- type: Div,
2286
- className: QuickPickItems$1,
2287
- id: QuickPickItems,
2288
- role: ListBox,
2289
- ariaActivedescendant: QuickPickItemActive,
2290
- onWheel: HandleWheel,
2291
- childCount: visibleItems.length
2292
- }, ...getQuickPickItemsVirtualDom(visibleItems)];
2170
+ const selectPick$6 = async pick => {
2171
+ const description = pick.description;
2172
+ const fileName = pick.label;
2173
+ const workspace = await getWorkspacePath();
2174
+ const absolutePath = `${workspace}/${description}/${fileName}`;
2175
+ await openUri(absolutePath);
2176
+ return {
2177
+ command: Hide
2178
+ };
2293
2179
  };
2294
2180
 
2295
- const renderItems = newState => {
2296
- const dom = getQuickPickVirtualDom(newState.visibleItems);
2297
- return ['Viewlet.setDom2', dom];
2181
+ const execute = async (method, ...params) => {
2182
+ // TODO
2298
2183
  };
2299
2184
 
2300
- const renderValue = newState => {
2301
- return ['Viewlet.send', newState.uid, /* method */SetValue, /* value */newState.value];
2185
+ const selectPick$5 = async item => {
2186
+ const rowIndex = Number.parseInt(item.label);
2187
+ const position = {
2188
+ rowIndex,
2189
+ columnIndex: 5
2190
+ };
2191
+ await execute(/* EditorSetCursor.editorSetCursor */'TODO', /* position */position);
2192
+ // TODO put cursor onto that line
2193
+ return {
2194
+ command: Hide
2195
+ };
2302
2196
  };
2303
2197
 
2304
- const getRenderer = diffType => {
2305
- switch (diffType) {
2306
- case RenderValue:
2307
- return renderValue;
2308
- case RenderCursorOffset:
2309
- return renderCursorOffset;
2310
- case RenderItems:
2311
- return renderItems;
2312
- case RenderFocusedIndex:
2313
- return renderFocusedIndex;
2314
- case Height:
2315
- return renderHeight;
2316
- case RenderFocus:
2317
- return renderFocus;
2318
- default:
2319
- throw new Error('unknown renderer');
2320
- }
2198
+ const selectPick$4 = async item => {
2199
+ // Command.execute(/* openView */ 549, /* viewName */ item.label)
2200
+ return {
2201
+ command: Hide
2202
+ };
2321
2203
  };
2322
2204
 
2323
- const applyRender = (oldState, newState, diffResult) => {
2324
- const commands = [];
2325
- const viewModel = createQuickPickViewModel(oldState, newState);
2326
- for (const item of diffResult) {
2327
- if (item === Height) {
2328
- continue;
2329
- }
2330
- if (item === RenderFocusedIndex) {
2331
- continue;
2332
- }
2333
- const fn = getRenderer(item);
2334
- commands.push(fn(viewModel));
2335
- }
2336
- return commands;
2205
+ const openWorkspaceFolder = uri => {
2206
+ return invoke$1(/* Workspace.setPath */'Workspace.setPath', /* path */uri);
2337
2207
  };
2338
2208
 
2339
- const render2 = (uid, diffResult) => {
2340
- const {
2341
- oldState,
2342
- newState
2343
- } = get(uid);
2344
- if (oldState === newState) {
2345
- return [];
2346
- }
2347
- set(uid, newState, newState);
2348
- const commands = applyRender(oldState, newState, diffResult);
2349
- return commands;
2209
+ // TODO selectPick should be independent of show/hide
2210
+ const selectPick$3 = async pick => {
2211
+ const path = `${pick.description}/${pick.label}`;
2212
+ await openWorkspaceFolder(path);
2213
+ return {
2214
+ command: Hide
2215
+ };
2350
2216
  };
2351
2217
 
2352
- const renderEventListeners = () => {
2353
- return [{
2354
- name: HandlePointerDown,
2355
- params: ['handlePointerDown', 'event.clientX', 'event.clientY'],
2356
- preventDefault: true
2357
- }, {
2358
- name: HandleWheel,
2359
- params: ['handleWheel', 'event.deltaMode', 'event.deltaY']
2360
- }, {
2361
- name: HandleBlur,
2362
- params: ['handleBlur']
2363
- }, {
2364
- name: HandleBeforeInput,
2365
- params: ['handleBeforeInput']
2366
- }, {
2367
- name: HandleInput,
2368
- params: ['handleInput', 'event.target.value']
2369
- }, {
2370
- name: HandleFocus,
2371
- params: ['handleFocus']
2372
- }];
2218
+ const selectPick$2 = async item => {
2219
+ return {
2220
+ command: Hide
2221
+ };
2373
2222
  };
2374
2223
 
2375
- const selectCurrentIndex = state => {
2376
- return selectIndex(state, state.focusedIndex);
2224
+ const selectPick$1 = async item => {
2225
+ // Command.execute(/* openView */ 549, /* viewName */ item.label)
2226
+ return {
2227
+ command: Hide
2228
+ };
2377
2229
  };
2378
2230
 
2379
- const findLabelIndex = (items, label) => {
2380
- for (let i = 0; i < items.length; i++) {
2381
- if (items[i].label === label) {
2382
- return i;
2383
- }
2231
+ const selectPick = async item => {
2232
+ return {
2233
+ command: Hide
2234
+ };
2235
+ };
2236
+
2237
+ const selectPicks = [selectPick$9, selectPick$8, selectPick$7, selectPick$6, selectPick$5, selectPick$4, selectPick$3, selectPick$2, selectPick$1, selectPick];
2238
+ const getPicks$2 = [getPicks$c, getPicks$b, getPicks$a, getPicks$9, getPicks$8, getPicks$7, getPicks$6, getPicks$5, getPicks$4, getPicks$3];
2239
+
2240
+ const select = selectPicks;
2241
+ const getPick$1 = getPicks$2;
2242
+ const getPicks$1 = id => {
2243
+ const fn = getPick$1[id];
2244
+ return fn;
2245
+ };
2246
+ const getSelect = id => {
2247
+ const fn = select[id];
2248
+ return fn;
2249
+ };
2250
+
2251
+ const getPicks = (id, searchValue) => {
2252
+ const fn = getPicks$1(id);
2253
+ return fn(searchValue);
2254
+ };
2255
+
2256
+ const getQuickPickSubProviderId = prefix => {
2257
+ switch (prefix) {
2258
+ case Command:
2259
+ return Commands$1;
2260
+ case Symbol$1:
2261
+ return Symbol$2;
2262
+ case WorkspaceSymbol$1:
2263
+ return WorkspaceSymbol$2;
2264
+ case GoToLine$1:
2265
+ return GoToLine$2;
2266
+ case View$2:
2267
+ return View$3;
2268
+ case Help$1:
2269
+ return Help$2;
2270
+ default:
2271
+ return File$2;
2384
2272
  }
2385
- return -1;
2386
2273
  };
2387
2274
 
2388
- const selectItem = async (state, label) => {
2389
- string(label);
2390
- const index = findLabelIndex(state.items, label);
2391
- if (index === -1) {
2275
+ // TODO when user types letters -> no need to query provider again -> just filter existing results
2276
+ const setValue = async (state, newValue) => {
2277
+ const {
2278
+ providerId,
2279
+ value,
2280
+ minLineY,
2281
+ maxLineY,
2282
+ fileIconCache
2283
+ } = state;
2284
+ if (value === newValue) {
2392
2285
  return state;
2393
2286
  }
2394
- return selectIndex(state, index);
2287
+ const prefix = getQuickPickPrefix(newValue);
2288
+ const subId = getQuickPickSubProviderId(prefix);
2289
+ const newPicks = await getPicks(subId, newValue);
2290
+ const filterValue = getFilterValue(providerId, newValue);
2291
+ const items = filterQuickPickItems(newPicks, filterValue);
2292
+ const focusedIndex = items.length === 0 ? -1 : 0;
2293
+ const sliced = items.slice(minLineY, maxLineY);
2294
+ const {
2295
+ newFileIconCache,
2296
+ icons
2297
+ } = await getQuickPickFileIcons(sliced, fileIconCache);
2298
+ return {
2299
+ ...state,
2300
+ picks: newPicks,
2301
+ items,
2302
+ focusedIndex,
2303
+ inputSource: Script,
2304
+ value: newValue,
2305
+ icons,
2306
+ fileIconCache: newFileIconCache
2307
+ };
2395
2308
  };
2396
2309
 
2397
- const wrapCommand = fn => {
2398
- const wrapped = async (uid, ...args) => {
2399
- const {
2400
- newState
2401
- } = get(uid);
2402
- const newerState = await fn(newState, ...args);
2403
- if (newState === newerState) {
2404
- return;
2405
- }
2406
- const latest = get(uid);
2407
- set(uid, latest.oldState, newerState);
2310
+ // TODO when user types letters -> no need to query provider again -> just filter existing results
2311
+ const handleInput = async (state, newValue, cursorOffset, inputSource = Script) => {
2312
+ if (state.value === newValue) {
2313
+ return state;
2314
+ }
2315
+ const newState = await setValue(state, newValue);
2316
+ return {
2317
+ ...newState,
2318
+ cursorOffset,
2319
+ inputSource
2408
2320
  };
2409
- return wrapped;
2410
2321
  };
2411
2322
 
2412
- const commandMap = {
2413
- 'QuickPick.addMenuEntries': add,
2414
- 'QuickPick.close': close,
2415
- 'QuickPick.create2': create,
2416
- 'QuickPick.diff2': diff2,
2417
- 'QuickPick.dispose': dispose,
2418
- 'QuickPick.focusFirst': wrapCommand(focusFirst),
2419
- 'QuickPick.focusIndex': wrapCommand(focusIndex),
2420
- 'QuickPick.focusLast': wrapCommand(focusLast),
2421
- 'QuickPick.focusNext': wrapCommand(focusNext),
2422
- 'QuickPick.focusPrevious': wrapCommand(focusPrevious),
2423
- 'QuickPick.getCommandIds': getCommandIds,
2424
- 'QuickPick.getKeyBindings': getKeyBindings,
2425
- 'QuickPick.handleBeforeInput': wrapCommand(handleBeforeInput),
2426
- 'QuickPick.handleBlur': wrapCommand(handleBlur),
2427
- 'QuickPick.handleClickAt': wrapCommand(handleClickAt),
2428
- 'QuickPick.handleFocus': wrapCommand(handleFocus),
2429
- 'QuickPick.handleInput': wrapCommand(handleInput),
2430
- 'QuickPick.handleWheel': wrapCommand(handleWheel),
2431
- 'QuickPick.loadContent': wrapCommand(loadContent),
2432
- 'QuickPick.render2': render2,
2433
- 'QuickPick.renderEventListeners': renderEventListeners,
2434
- 'QuickPick.selectCurrentIndex': wrapCommand(selectCurrentIndex),
2435
- 'QuickPick.selectIndex': wrapCommand(selectIndex),
2436
- 'QuickPick.selectItem': wrapCommand(selectItem),
2437
- 'QuickPick.setDeltaY': wrapCommand(setDeltaY),
2438
- 'QuickPick.setValue': wrapCommand(setValue)
2323
+ const handleBeforeInput = (state, inputType, data, selectionStart, selectionEnd) => {
2324
+ string(inputType);
2325
+ number(selectionStart);
2326
+ number(selectionEnd);
2327
+ const {
2328
+ value
2329
+ } = state;
2330
+ const {
2331
+ newValue,
2332
+ cursorOffset
2333
+ } = getNewValue(value, inputType, data, selectionStart, selectionEnd);
2334
+ return handleInput(state, newValue, cursorOffset, User);
2439
2335
  };
2440
2336
 
2441
- const getColorThemeNames = async () => {
2442
- return invoke$1(/* Ajax.getJson */'ColorTheme.getColorThemeNames');
2337
+ const handleBlur = async state => {
2338
+ // TODO fix virtual dom diffing so that input isn't destroyed and loses focus when rerendering
2339
+ // await CloseWidget.closeWidget(state.uid)
2340
+ return state;
2443
2341
  };
2444
2342
 
2445
- const toProtoVisibleItem$2 = name => {
2446
- const pick = {
2447
- label: name,
2448
- description: '',
2449
- fileIcon: '',
2450
- icon: '',
2451
- matches: [],
2452
- direntType: 0,
2453
- uri: ''
2454
- };
2455
- return pick;
2456
- };
2457
- const getPicks$a = async searchValue => {
2458
- const colorThemeNames = await getColorThemeNames();
2459
- const picks = colorThemeNames.map(toProtoVisibleItem$2);
2460
- return picks;
2343
+ const getIndex = (top, headerHeight, itemHeight, y) => {
2344
+ const relativeY = y - top - headerHeight;
2345
+ const index = Math.floor(relativeY / itemHeight);
2346
+ return index;
2461
2347
  };
2462
2348
 
2463
- const handleError = async (error, notify = true, prefix = '') => {
2464
- console.error(error);
2465
- };
2466
- const showErrorDialog = async error => {
2467
- const code = error.code;
2468
- const message = error.message;
2469
- const stack = error.stack;
2470
- const name = error.name;
2471
- const errorInfo = {
2472
- code,
2473
- message,
2474
- stack,
2475
- name
2476
- };
2477
- await invoke$1('ErrorHandling.showErrorDialog', errorInfo);
2478
- };
2479
- const warn = (...args) => {
2480
- console.warn(...args);
2349
+ const getPick = (items, index) => {
2350
+ array(items);
2351
+ number(index);
2352
+ // if (index < state.recentPicks.length) {
2353
+ // return state.recentPicks[index]
2354
+ // }
2355
+ // index -= state.recentPicks.length
2356
+ if (index < items.length) {
2357
+ return items[index];
2358
+ }
2359
+ console.warn('no pick matching index', index);
2360
+ return undefined;
2481
2361
  };
2482
2362
 
2483
- // TODO combine Ajax with cache (specify strategy: cacheFirst, networkFirst)
2484
- const getBuiltinPicks = async () => {
2485
- const builtinPicks = getAll();
2486
- return builtinPicks;
2487
- };
2488
- const prefixIdWithExt = item => {
2489
- if (!item.label) {
2490
- warn('[QuickPick] item has missing label', item);
2363
+ const selectIndex = async (state, index, button = /* left */0) => {
2364
+ const {
2365
+ minLineY,
2366
+ items,
2367
+ value
2368
+ } = state;
2369
+ const actualIndex = index + minLineY;
2370
+ const pick = getPick(items, actualIndex);
2371
+ if (!pick) {
2372
+ return state;
2491
2373
  }
2492
- if (!item.id) {
2493
- warn('[QuickPick] item has missing id', item);
2374
+ const prefix = getQuickPickPrefix(value);
2375
+ const subId = getQuickPickSubProviderId(prefix);
2376
+ const fn = getSelect(subId);
2377
+ const selectPickResult = await fn(pick);
2378
+ object(selectPickResult);
2379
+ string(selectPickResult.command);
2380
+ const {
2381
+ command
2382
+ } = selectPickResult;
2383
+ switch (command) {
2384
+ case Hide:
2385
+ await closeWidget(state.uid);
2386
+ return state;
2387
+ default:
2388
+ return state;
2494
2389
  }
2495
- return {
2496
- ...item,
2497
- id: `ext.${item.id}`,
2498
- label: item.label || item.id
2499
- };
2390
+
2391
+ // TODO recent picks should be per provider
2392
+ // if (!state.recentPickIds.has(pick.id)) {
2393
+ // state.recentPicks.unshift(pick)
2394
+ // state.recentPickIds.add(pick.id)
2395
+ // }
2396
+ // if (state.recentPicks.length > RECENT_PICKS_MAX_SIZE) {
2397
+ // const last = state.recentPicks.pop()
2398
+ // state.recentPickIds.delete(last.id)
2399
+ // }
2500
2400
  };
2501
- const getExtensionPicks = async () => {
2502
- try {
2503
- // TODO don't call this every time
2504
- const extensionPicks = await invoke$1('ExtensionHost.getCommands');
2505
- if (!extensionPicks) {
2506
- return [];
2507
- }
2508
- const mappedPicks = extensionPicks.map(prefixIdWithExt);
2509
- return mappedPicks;
2510
- } catch (error) {
2511
- console.error(`Failed to get extension picks: ${error}`);
2512
- return [];
2513
- }
2401
+
2402
+ const handleClickAt = (state, x, y) => {
2403
+ const {
2404
+ top,
2405
+ headerHeight,
2406
+ itemHeight
2407
+ } = state;
2408
+ const index = getIndex(top, headerHeight, itemHeight, y);
2409
+ return selectIndex(state, index);
2514
2410
  };
2515
- const toProtoVisibleItem$1 = item => {
2516
- const pick = {
2517
- label: item.label,
2518
- description: '',
2519
- fileIcon: '',
2520
- icon: '',
2521
- matches: [],
2522
- direntType: 0,
2523
- uri: ''
2524
- };
2525
- // @ts-ignore
2526
- pick.id = item.id;
2527
- return pick;
2411
+
2412
+ const setFocus = async focusKey => {
2413
+ await invoke$1('Focus.setFocus', focusKey);
2528
2414
  };
2529
- const getPicks$9 = async () => {
2530
- // TODO get picks in parallel
2531
- const builtinPicks = await getBuiltinPicks();
2532
- const extensionPicks = await getExtensionPicks();
2533
- const allPicks = [...builtinPicks, ...extensionPicks];
2534
- const converted = allPicks.map(toProtoVisibleItem$1);
2535
- return converted;
2415
+
2416
+ const handleFocus = async state => {
2417
+ // TODO fix virtual dom diffing so that input isn't destroyed and loses focus when rerendering
2418
+ await setFocus(FocusQuickPickInput);
2419
+ // await CloseWidget.closeWidget(state.uid)
2420
+ return state;
2536
2421
  };
2537
2422
 
2538
- const getPicks$8 = async searchValue => {
2539
- const items = state$3.args[1] || [];
2540
- return items;
2423
+ const getDefaultValue = id => {
2424
+ switch (id) {
2425
+ case EveryThing$1:
2426
+ return Command;
2427
+ default:
2428
+ return '';
2429
+ }
2541
2430
  };
2542
2431
 
2543
- // TODO use numeric enum for quickpick entry id
2432
+ const Commands = 'quickPick://commands';
2433
+ const EveryThing = 'quickPick://everything';
2434
+ const Recent = 'quickPick://recent';
2435
+ const ColorTheme = 'quickPick://color-theme';
2436
+ const Symbol = 'quickPick://symbol';
2437
+ const View = 'quickPick://view';
2438
+ const Help = 'quickPick://help';
2439
+ const WorkspaceSymbol = 'quickPick://workspace-symbol';
2440
+ const GoToLine = 'quickPick://go-to-line';
2441
+
2544
2442
  const getQuickPickProviderId = prefix => {
2545
2443
  switch (prefix) {
2546
- case Command:
2547
- return Commands;
2444
+ case Commands:
2548
2445
  case Symbol:
2549
- return Symbol$1;
2550
2446
  case WorkspaceSymbol:
2551
- return WorkspaceSymbol$1;
2447
+ case EveryThing:
2552
2448
  case GoToLine:
2553
- return GoToLine$1;
2554
2449
  case View:
2555
- return View$1;
2450
+ case Help:
2451
+ return EveryThing$1;
2452
+ case ColorTheme:
2453
+ return ColorTheme$1;
2454
+ case Recent:
2455
+ return Recent$1;
2556
2456
  default:
2557
2457
  return File$2;
2558
2458
  }
2559
2459
  };
2560
2460
 
2561
- const state$1 = {
2562
- provider: Noop,
2563
- prefix: 'string-that-should-never-match-another-string'
2461
+ const noop = args => {};
2462
+ const setArgsCustom = args => {
2463
+ state$1.args = args;
2564
2464
  };
2565
-
2566
- const getPicks$7 = async value => {
2567
- const prefix = getQuickPickPrefix(value);
2568
- const providerId = getQuickPickProviderId(prefix);
2569
-
2570
- // TODO race condition
2571
- if (state$1.prefix !== prefix) {
2572
- state$1.prefix = prefix;
2573
- state$1.provider = providerId;
2465
+ const getFn = id => {
2466
+ switch (id) {
2467
+ case Custom:
2468
+ return setArgsCustom;
2469
+ default:
2470
+ return noop;
2574
2471
  }
2575
- // TODO this line is a bit duplicated with getFilterValue
2576
- const slicedValue = value.slice(prefix.length).trimStart();
2577
- const picks = await getPicks$b(providerId, slicedValue);
2578
- return picks;
2579
- };
2580
-
2581
- const emptyMatches = [];
2582
-
2583
- const getWorkspacePath = async () => {
2584
- return invoke$1('Workspace.getPath');
2585
2472
  };
2586
-
2587
- const RE_PROTOCOL = /^([a-z-]+):\/\//;
2588
- const getProtocol = uri => {
2589
- const protocolMatch = uri.match(RE_PROTOCOL);
2590
- if (protocolMatch) {
2591
- return protocolMatch[1];
2592
- }
2593
- return '';
2473
+ const setArgs = (id, args) => {
2474
+ const fn = getFn(id);
2475
+ return fn(args);
2594
2476
  };
2595
2477
 
2596
- const state = Object.create(null);
2597
- const register = modules => {
2598
- Object.assign(state, modules);
2599
- };
2600
- const getModule = protocol => {
2601
- return state[protocol];
2478
+ const loadContent = async state => {
2479
+ const {
2480
+ uri,
2481
+ args,
2482
+ fileIconCache
2483
+ } = state;
2484
+ const id = getQuickPickProviderId(uri);
2485
+ const value = getDefaultValue(id);
2486
+ const prefix = getQuickPickPrefix(value);
2487
+ const subId = getQuickPickSubProviderId(prefix);
2488
+ setArgs(subId, args);
2489
+ const newPicks = await getPicks(subId, value);
2490
+ array(newPicks);
2491
+ const filterValue = getFilterValue(id, value);
2492
+ const items = filterQuickPickItems(newPicks, filterValue);
2493
+ const minLineY = 0;
2494
+ const maxLineY = Math.min(minLineY + state.maxVisibleItems, newPicks.length);
2495
+ const sliced = newPicks.slice(minLineY, maxLineY);
2496
+ const {
2497
+ newFileIconCache,
2498
+ icons
2499
+ } = await getQuickPickFileIcons(sliced, fileIconCache);
2500
+ return {
2501
+ ...state,
2502
+ picks: newPicks,
2503
+ items,
2504
+ focusedIndex: 0,
2505
+ state: Finished,
2506
+ minLineY,
2507
+ maxLineY,
2508
+ value,
2509
+ cursorOffset: value.length,
2510
+ inputSource: Script,
2511
+ focused: true,
2512
+ fileIconCache: newFileIconCache,
2513
+ icons,
2514
+ providerId: id
2515
+ };
2602
2516
  };
2603
2517
 
2604
- const searchFile$5 = async (path, value, prepare, assetDir) => {
2605
- const protocol = getProtocol(path);
2606
- // TODO call different providers depending on protocol
2607
- const fn = getModule(protocol);
2608
- const result = await fn(path, value, prepare, assetDir);
2609
- return result;
2518
+ const getVisible$1 = (items, minLineY, maxLineY, icons) => {
2519
+ const range = items.slice(minLineY, maxLineY);
2520
+ const protoVisibleItems = range.map((item, index) => {
2521
+ return {
2522
+ ...item,
2523
+ fileIcon: icons[index]
2524
+ };
2525
+ });
2526
+ return protoVisibleItems;
2610
2527
  };
2611
2528
 
2612
- // TODO this should be in FileSystem module
2613
- const pathBaseName = path => {
2614
- return path.slice(path.lastIndexOf('/') + 1);
2615
- };
2529
+ const emptyHighlightSections = [];
2616
2530
 
2617
- // TODO this should be in FileSystem module
2618
- const pathDirName = path => {
2619
- const pathSeparator = '/';
2620
- const index = path.lastIndexOf(pathSeparator);
2621
- if (index === -1) {
2622
- return '';
2531
+ const getHighlightSections = (highlights, label) => {
2532
+ if (highlights.length === 0) {
2533
+ return emptyHighlightSections;
2623
2534
  }
2624
- return path.slice(0, index);
2625
- };
2626
-
2627
- const searchFile$4 = async (path, value) => {
2628
- const prepare = true;
2629
- const files = await searchFile$5(/* path */path, /* searchTerm */value, prepare, '');
2630
- return files;
2631
- };
2632
- const convertToPick = uri => {
2633
- const baseName = pathBaseName(uri);
2634
- const dirName = pathDirName(uri);
2635
- return {
2636
- description: dirName,
2637
- direntType: File$1,
2638
- fileIcon: '',
2639
- icon: '',
2640
- label: baseName,
2641
- matches: emptyMatches,
2642
- uri
2535
+ const sections = [];
2536
+ let position = 0;
2537
+ for (let i = 0; i < highlights.length; i += 2) {
2538
+ const highlightStart = highlights[i];
2539
+ const highlightEnd = highlights[i + 1];
2540
+ if (position < highlightStart) {
2541
+ const beforeText = label.slice(position, highlightStart);
2542
+ sections.push({
2543
+ highlighted: false,
2544
+ text: beforeText
2545
+ });
2546
+ }
2547
+ const highlightText = label.slice(highlightStart, highlightEnd);
2548
+ sections.push({
2549
+ highlighted: true,
2550
+ text: highlightText
2551
+ });
2552
+ position = highlightEnd;
2553
+ }
2554
+ if (position < label.length) {
2555
+ const afterText = label.slice(position);
2556
+ sections.push({
2557
+ highlighted: false,
2558
+ text: afterText
2559
+ });
2560
+ }
2561
+ return sections;
2562
+ };
2563
+
2564
+ const getVisible = (setSize, protoVisibleItems, minLineY, focusedIndex) => {
2565
+ const visibleItems = protoVisibleItems.map((visibleItem, i) => {
2566
+ const highlights = visibleItem.matches.slice(1);
2567
+ const sections = getHighlightSections(highlights, visibleItem.label);
2568
+ return {
2569
+ ...visibleItem,
2570
+ posInSet: minLineY + i + 1,
2571
+ setSize,
2572
+ isActive: i === focusedIndex,
2573
+ highlights: sections
2574
+ };
2575
+ });
2576
+ return visibleItems;
2577
+ };
2578
+
2579
+ const createQuickPickViewModel = (oldState, newState) => {
2580
+ const protoVisibleItems = getVisible$1(newState.items, newState.minLineY, newState.maxLineY, newState.icons);
2581
+ const visibleItems = getVisible(newState.items.length, protoVisibleItems, newState.minLineY, newState.focusedIndex);
2582
+ const oldFocusedIndex = oldState.focusedIndex - oldState.minLineY;
2583
+ const newFocusedIndex = newState.focusedIndex - newState.minLineY;
2584
+ const maxLineY = Math.min(newState.maxLineY, newState.items.length);
2585
+ const itemCount = maxLineY - newState.minLineY;
2586
+ const height = itemCount * newState.itemHeight;
2587
+ return {
2588
+ visibleItems,
2589
+ value: newState.value,
2590
+ cursorOffset: newState.cursorOffset,
2591
+ focused: newState.focused,
2592
+ height,
2593
+ oldFocusedIndex,
2594
+ newFocusedIndex,
2595
+ uid: newState.uid
2643
2596
  };
2644
2597
  };
2645
2598
 
2646
- // TODO handle files differently
2647
- // e.g. when there are many files, don't need
2648
- // to compute the fileIcon for all files
2599
+ const SetCursorOffset = 'setCursorOffset';
2600
+ const SetFocusedIndex = 'setFocusedIndex';
2601
+ const SetItemsHeight = 'setItemsHeight';
2649
2602
 
2650
- const getPicks$6 = async searchValue => {
2651
- // TODO cache workspace path
2652
- const workspace = await getWorkspacePath();
2653
- if (!workspace) {
2654
- return [];
2655
- }
2656
- const files = await searchFile$4(workspace, searchValue);
2657
- const picks = files.map(convertToPick);
2658
- return picks;
2603
+ const renderCursorOffset = newState => {
2604
+ return ['Viewlet.send', newState.uid, /* method */SetCursorOffset, /* cursorOffset */newState.cursorOffset];
2659
2605
  };
2660
2606
 
2661
- const getPicks$5 = async () => {
2662
- const picks = [{
2663
- label: '1',
2664
- description: '',
2665
- icon: '',
2666
- fileIcon: '',
2667
- matches: [],
2668
- direntType: None$2,
2669
- uri: ''
2670
- }, {
2671
- label: '2',
2672
- description: '',
2673
- icon: '',
2674
- fileIcon: '',
2675
- matches: [],
2676
- direntType: None$2,
2677
- uri: ''
2678
- }, {
2679
- label: '3',
2680
- description: '',
2681
- icon: '',
2682
- fileIcon: '',
2683
- matches: [],
2684
- direntType: None$2,
2685
- uri: ''
2686
- }, {
2687
- label: '4',
2688
- description: '',
2689
- icon: '',
2690
- fileIcon: '',
2691
- matches: [],
2692
- direntType: None$2,
2693
- uri: ''
2694
- }, {
2695
- label: '5',
2696
- description: '',
2697
- icon: '',
2698
- fileIcon: '',
2699
- matches: [],
2700
- direntType: None$2,
2701
- uri: ''
2702
- }, {
2703
- label: '6',
2704
- description: '',
2705
- icon: '',
2706
- fileIcon: '',
2707
- matches: [],
2708
- direntType: None$2,
2709
- uri: ''
2710
- }];
2711
- return picks;
2607
+ const QuickPickInput = 'QuickPickInput';
2608
+
2609
+ const renderFocus = newState => {
2610
+ return ['Viewlet.focusElementByName', QuickPickInput];
2712
2611
  };
2713
2612
 
2714
- const getRecentlyOpened = () => {
2715
- return invoke$1(/* RecentlyOpened.getRecentlyOpened */'RecentlyOpened.getRecentlyOpened');
2613
+ const renderFocusedIndex = newState => {
2614
+ return ['Viewlet.send', newState.uid, /* method */SetFocusedIndex, /* oldFocusedIndex */newState.oldFocusedIndex, /* newFocusedIndex */newState.newFocusedIndex];
2716
2615
  };
2717
2616
 
2718
- const toProtoVisibleItem = uri => {
2617
+ const renderHeight = newState => {
2618
+ if (newState.height === 0) {
2619
+ return ['Viewlet.send', newState.uid, /* method */SetItemsHeight, /* height */20];
2620
+ }
2621
+ return ['Viewlet.send', newState.uid, /* method */SetItemsHeight, /* height */newState.height];
2622
+ };
2623
+
2624
+ const ComboBox = 'combobox';
2625
+ const ListBox = 'listbox';
2626
+ const None = 'none';
2627
+ const Option = 'option';
2628
+
2629
+ const FileIcon = 'FileIcon';
2630
+ const InputBox = 'InputBox';
2631
+ const Label = 'Label';
2632
+ const MaskIcon = 'MaskIcon';
2633
+ const QuickPick$1 = 'QuickPick';
2634
+ const QuickPickHeader = 'QuickPickHeader';
2635
+ const QuickPickHighlight = 'QuickPickHighlight';
2636
+ const QuickPickItem = 'QuickPickItem';
2637
+ const QuickPickItemActive$1 = 'QuickPickItemActive';
2638
+ const QuickPickItemDescription = 'QuickPickItemDescription';
2639
+ const QuickPickItemLabel = 'QuickPickItemLabel';
2640
+ const QuickPickItems$1 = 'QuickPickItems';
2641
+ const QuickPickMaskIcon = 'QuickPickMaskIcon';
2642
+ const QuickPickStatus = 'QuickPickStatus';
2643
+ const Viewlet = 'Viewlet';
2644
+
2645
+ const HandleWheel = 'handleWheel';
2646
+ const HandlePointerDown = 'handlePointerDown';
2647
+ const HandleBeforeInput = 'handleBeforeInput';
2648
+ const HandleBlur = 'handleBlur';
2649
+ const HandleFocus = 'handleFocus';
2650
+ const HandleInput = 'handleInput';
2651
+
2652
+ const QuickPick = 'QuickPick';
2653
+ const QuickPickItems = 'QuickPickItems';
2654
+ const QuickPickItemActive = 'QuickPickItemActive';
2655
+
2656
+ const Div = 4;
2657
+ const Input = 6;
2658
+ const Span = 8;
2659
+ const Img = 17;
2660
+
2661
+ const getQuickPickInputVirtualDom = () => {
2662
+ const ariaLabel = typeNameofCommandToRun();
2719
2663
  return {
2720
- label: uri,
2721
- description: '',
2722
- fileIcon: '',
2723
- icon: '',
2724
- matches: [],
2725
- direntType: Directory,
2726
- uri: uri
2664
+ type: Input,
2665
+ className: InputBox,
2666
+ spellcheck: false,
2667
+ autocapitalize: 'off',
2668
+ inputType: 'text',
2669
+ childCount: 0,
2670
+ role: ComboBox,
2671
+ name: QuickPickInput,
2672
+ onBeforeInput: HandleBeforeInput,
2673
+ onBlur: HandleBlur,
2674
+ onInput: HandleInput,
2675
+ onFocus: HandleFocus,
2676
+ ariaLabel: ariaLabel,
2677
+ ariaAutoComplete: 'list',
2678
+ ariaExpanded: true,
2679
+ autocomplete: 'off'
2727
2680
  };
2728
2681
  };
2729
- const getPicks$4 = async () => {
2730
- const recentlyOpened = await getRecentlyOpened();
2731
- const picks = recentlyOpened.map(toProtoVisibleItem);
2732
- return picks;
2733
- };
2734
2682
 
2735
- const getPicks$3 = async () => {
2736
- const picks = [];
2737
- return picks;
2683
+ const getQuickPickHeaderVirtualDom = () => {
2684
+ return [{
2685
+ type: Div,
2686
+ className: QuickPickHeader,
2687
+ childCount: 1
2688
+ }, getQuickPickInputVirtualDom()];
2738
2689
  };
2739
2690
 
2740
- const getPicks$2 = async () => {
2741
- // const views = ViewService.getViews()
2742
- // const picks = views.map(toPick)
2743
- // return picks
2744
- return [];
2691
+ const getFileIconVirtualDom = icon => {
2692
+ return {
2693
+ type: Img,
2694
+ className: FileIcon,
2695
+ src: icon,
2696
+ role: None,
2697
+ childCount: 0
2698
+ };
2745
2699
  };
2746
2700
 
2747
- const getPicks$1 = async () => {
2748
- const picks = [];
2749
- return picks;
2701
+ const mergeClassNames = (...classNames) => {
2702
+ return classNames.filter(Boolean).join(' ');
2750
2703
  };
2751
-
2752
- const selectPick$9 = async pick => {
2753
- const id = pick.label;
2754
- await setColorTheme(/* colorThemeId */id);
2704
+ const Text = 12;
2705
+ const text = data => {
2755
2706
  return {
2756
- command: Hide
2707
+ type: Text,
2708
+ text: data,
2709
+ childCount: 0
2757
2710
  };
2758
2711
  };
2759
2712
 
2760
- const shouldHide = item => {
2761
- if (item.id === 'Viewlet.openWidget' && item.args[0] === 'QuickPick') {
2762
- return false;
2713
+ const quickPickHighlight = {
2714
+ type: Span,
2715
+ className: QuickPickHighlight,
2716
+ childCount: 1
2717
+ };
2718
+ const getHighlights = (sections, label) => {
2719
+ const labelDom = {
2720
+ type: Div,
2721
+ className: QuickPickItemLabel,
2722
+ childCount: 0
2723
+ };
2724
+ const nodes = [labelDom];
2725
+ if (sections.length === 0) {
2726
+ labelDom.childCount++;
2727
+ nodes.push(text(label));
2728
+ } else {
2729
+ for (const section of sections) {
2730
+ if (section.highlighted) {
2731
+ labelDom.childCount++;
2732
+ nodes.push(quickPickHighlight, text(section.text));
2733
+ } else {
2734
+ labelDom.childCount++;
2735
+ nodes.push(text(section.text));
2736
+ }
2737
+ }
2738
+ }
2739
+ return nodes;
2740
+ };
2741
+
2742
+ const getQuickPickItemVirtualDom = visibleItem => {
2743
+ const {
2744
+ posInSet,
2745
+ label,
2746
+ setSize,
2747
+ isActive,
2748
+ description,
2749
+ icon,
2750
+ highlights,
2751
+ fileIcon
2752
+ } = visibleItem;
2753
+ const dom = [];
2754
+ dom.push({
2755
+ type: Div,
2756
+ className: QuickPickItem,
2757
+ role: Option,
2758
+ ariaPosInSet: posInSet,
2759
+ ariaSetSize: setSize,
2760
+ childCount: 1
2761
+ });
2762
+ const parent = dom[0];
2763
+ if (isActive) {
2764
+ // @ts-ignore
2765
+ parent.id = QuickPickItemActive;
2766
+ parent.className += ' ' + QuickPickItemActive$1;
2767
+ }
2768
+ if (fileIcon) {
2769
+ parent.childCount++;
2770
+ dom.push(getFileIconVirtualDom(fileIcon));
2771
+ } else if (icon) {
2772
+ parent.childCount++;
2773
+ dom.push({
2774
+ type: Div,
2775
+ className: mergeClassNames(QuickPickMaskIcon, MaskIcon, `MaskIcon${icon}`),
2776
+ childCount: 0
2777
+ });
2763
2778
  }
2764
- return true;
2765
- };
2766
- const selectPickBuiltin = async item => {
2767
- const args = item.args || [];
2768
- // TODO ids should be all numbers for efficiency -> also directly can call command
2769
- await invoke$1(item.id, ...args);
2770
- if (shouldHide(item)) {
2771
- return {
2772
- command: Hide
2773
- };
2779
+ const highlightDom = getHighlights(highlights, label);
2780
+ dom.push(...highlightDom);
2781
+ if (description) {
2782
+ parent.childCount++;
2783
+ dom.push({
2784
+ type: Div,
2785
+ className: QuickPickItemDescription,
2786
+ childCount: 1
2787
+ }, text(description));
2774
2788
  }
2775
- return {
2776
- command: KeepOpen
2777
- };
2789
+ return dom;
2778
2790
  };
2779
- const selectPickExtension = async item => {
2780
- const id = item.id.slice(4); // TODO lots of string allocation with 'ext.' find a better way to separate builtin commands from extension commands
2781
- try {
2782
- await invoke$1('ExtensionHost.executeCommand', id);
2783
- } catch (error) {
2784
- await handleError(error, false);
2785
- await showErrorDialog(error);
2786
- }
2787
- return {
2788
- command: Hide
2789
- };
2791
+
2792
+ const getQuickPickNoResultsVirtualDom = () => {
2793
+ const noResults$1 = noResults();
2794
+ return [{
2795
+ type: Div,
2796
+ className: mergeClassNames(QuickPickItem, QuickPickItemActive$1, QuickPickStatus),
2797
+ childCount: 1
2798
+ }, {
2799
+ type: Div,
2800
+ className: Label,
2801
+ childCount: 1
2802
+ }, text(noResults$1)];
2790
2803
  };
2791
- const selectPick$8 = async item => {
2792
- // @ts-ignore
2793
- const id = item.id;
2794
- if (id.startsWith('ext.')) {
2795
- return selectPickExtension(item);
2804
+
2805
+ const getQuickPickItemsVirtualDom = visibleItems => {
2806
+ if (visibleItems.length === 0) {
2807
+ return getQuickPickNoResultsVirtualDom();
2796
2808
  }
2797
- return selectPickBuiltin(item);
2809
+ const dom = visibleItems.flatMap(getQuickPickItemVirtualDom);
2810
+ return dom;
2798
2811
  };
2799
2812
 
2800
- const selectPick$7 = async pick => {
2801
- const {
2802
- args
2803
- } = state$3;
2804
- const resolve = args[2];
2805
- resolve(pick);
2806
- return {
2807
- command: Hide
2808
- };
2813
+ const getQuickPickVirtualDom = visibleItems => {
2814
+ const quickOpen$1 = quickOpen();
2815
+ return [{
2816
+ type: Div,
2817
+ className: mergeClassNames(Viewlet, QuickPick$1),
2818
+ childCount: 2,
2819
+ id: QuickPick,
2820
+ ariaLabel: quickOpen$1
2821
+ }, ...getQuickPickHeaderVirtualDom(), {
2822
+ type: Div,
2823
+ className: QuickPickItems$1,
2824
+ id: QuickPickItems,
2825
+ role: ListBox,
2826
+ ariaActivedescendant: QuickPickItemActive,
2827
+ onWheel: HandleWheel,
2828
+ onPointerDown: HandlePointerDown,
2829
+ childCount: visibleItems.length
2830
+ }, ...getQuickPickItemsVirtualDom(visibleItems)];
2809
2831
  };
2810
2832
 
2811
- const selectPick$6 = item => {
2812
- const {
2813
- provider
2814
- } = state$1;
2815
- const fn = getSelect(provider);
2816
- return fn(item);
2833
+ const renderItems = newState => {
2834
+ const dom = getQuickPickVirtualDom(newState.visibleItems);
2835
+ return ['Viewlet.setDom2', dom];
2817
2836
  };
2818
2837
 
2819
- const openUri = async uri => {
2820
- await invoke$1(/* Main.openUri */'Main.openUri', /* uri */uri);
2838
+ const renderValue = newState => {
2839
+ return ['Viewlet.setValueByName', QuickPickInput, /* value */newState.value];
2821
2840
  };
2822
2841
 
2823
- const selectPick$5 = async pick => {
2824
- const description = pick.description;
2825
- const fileName = pick.label;
2826
- const workspace = await getWorkspacePath();
2827
- const absolutePath = `${workspace}/${description}/${fileName}`;
2828
- await openUri(absolutePath);
2829
- return {
2830
- command: Hide
2831
- };
2842
+ const getRenderer = diffType => {
2843
+ switch (diffType) {
2844
+ case RenderValue:
2845
+ return renderValue;
2846
+ case RenderCursorOffset:
2847
+ return renderCursorOffset;
2848
+ case RenderItems:
2849
+ return renderItems;
2850
+ case RenderFocusedIndex:
2851
+ return renderFocusedIndex;
2852
+ case Height:
2853
+ return renderHeight;
2854
+ case RenderFocus:
2855
+ return renderFocus;
2856
+ default:
2857
+ throw new Error('unknown renderer');
2858
+ }
2832
2859
  };
2833
2860
 
2834
- const execute = async (method, ...params) => {
2835
- // TODO
2861
+ const applyRender = (oldState, newState, diffResult) => {
2862
+ const commands = [];
2863
+ const viewModel = createQuickPickViewModel(oldState, newState);
2864
+ for (const item of diffResult) {
2865
+ if (item === Height) {
2866
+ continue;
2867
+ }
2868
+ if (item === RenderFocusedIndex) {
2869
+ continue;
2870
+ }
2871
+ const fn = getRenderer(item);
2872
+ commands.push(fn(viewModel));
2873
+ }
2874
+ return commands;
2836
2875
  };
2837
2876
 
2838
- const selectPick$4 = async item => {
2839
- const rowIndex = Number.parseInt(item.label);
2840
- const position = {
2841
- rowIndex,
2842
- columnIndex: 5
2843
- };
2844
- await execute(/* EditorSetCursor.editorSetCursor */'TODO', /* position */position);
2845
- // TODO put cursor onto that line
2846
- return {
2847
- command: Hide
2848
- };
2877
+ const render2 = (uid, diffResult) => {
2878
+ const {
2879
+ oldState,
2880
+ newState
2881
+ } = get(uid);
2882
+ if (oldState === newState) {
2883
+ return [];
2884
+ }
2885
+ set(uid, newState, newState);
2886
+ const commands = applyRender(oldState, newState, diffResult);
2887
+ return commands;
2849
2888
  };
2850
2889
 
2851
- const openWorkspaceFolder = uri => {
2852
- return invoke$1(/* Workspace.setPath */'Workspace.setPath', /* path */uri);
2890
+ const renderEventListeners = () => {
2891
+ return [{
2892
+ name: HandlePointerDown,
2893
+ params: ['handleClickAt', 'event.clientX', 'event.clientY'],
2894
+ preventDefault: true
2895
+ }, {
2896
+ name: HandleWheel,
2897
+ params: ['handleWheel', 'event.deltaMode', 'event.deltaY'],
2898
+ passive: true
2899
+ }, {
2900
+ name: HandleBlur,
2901
+ params: ['handleBlur']
2902
+ }, {
2903
+ name: HandleBeforeInput,
2904
+ params: ['handleBeforeInput']
2905
+ }, {
2906
+ name: HandleInput,
2907
+ params: ['handleInput', 'event.target.value']
2908
+ }, {
2909
+ name: HandleFocus,
2910
+ params: ['handleFocus']
2911
+ }];
2853
2912
  };
2854
2913
 
2855
- // TODO selectPick should be independent of show/hide
2856
- const selectPick$3 = async pick => {
2857
- const path = `${pick.description}/${pick.label}`;
2858
- await openWorkspaceFolder(path);
2859
- return {
2860
- command: Hide
2861
- };
2914
+ const selectCurrentIndex = state => {
2915
+ return selectIndex(state, state.focusedIndex);
2862
2916
  };
2863
2917
 
2864
- const selectPick$2 = async item => {
2865
- return {
2866
- command: Hide
2867
- };
2918
+ const findLabelIndex = (items, label) => {
2919
+ for (let i = 0; i < items.length; i++) {
2920
+ if (items[i].label === label) {
2921
+ return i;
2922
+ }
2923
+ }
2924
+ return -1;
2868
2925
  };
2869
2926
 
2870
- const selectPick$1 = async item => {
2871
- // Command.execute(/* openView */ 549, /* viewName */ item.label)
2872
- return {
2873
- command: Hide
2874
- };
2927
+ const selectItem = async (state, label) => {
2928
+ string(label);
2929
+ const index = findLabelIndex(state.items, label);
2930
+ if (index === -1) {
2931
+ return state;
2932
+ }
2933
+ return selectIndex(state, index);
2875
2934
  };
2876
2935
 
2877
- const selectPick = async item => {
2878
- return {
2879
- command: Hide
2936
+ const wrapCommand = fn => {
2937
+ const wrapped = async (uid, ...args) => {
2938
+ const {
2939
+ newState
2940
+ } = get(uid);
2941
+ const newerState = await fn(newState, ...args);
2942
+ if (newState === newerState) {
2943
+ return;
2944
+ }
2945
+ const latest = get(uid);
2946
+ set(uid, latest.oldState, newerState);
2880
2947
  };
2948
+ return wrapped;
2881
2949
  };
2882
2950
 
2883
- const selectPicks = {
2884
- [ColorTheme]: selectPick$9,
2885
- [CommandPalette]: selectPick$6,
2886
- [Commands]: selectPick$8,
2887
- [Custom]: selectPick$7,
2888
- [EveryThing]: selectPick$6,
2889
- [File$2]: selectPick$5,
2890
- [GoToLine$1]: selectPick$4,
2891
- [Recent]: selectPick$3,
2892
- [Symbol$1]: selectPick$2,
2893
- [View$1]: selectPick$1,
2894
- [WorkspaceSymbol$1]: selectPick
2895
- };
2896
- const getPicks = {
2897
- [ColorTheme]: getPicks$a,
2898
- [CommandPalette]: getPicks$7,
2899
- [Commands]: getPicks$9,
2900
- [Custom]: getPicks$8,
2901
- [EveryThing]: getPicks$7,
2902
- [GoToLine$1]: getPicks$5,
2903
- [File$2]: getPicks$6,
2904
- [Recent]: getPicks$4,
2905
- [Symbol$1]: getPicks$3,
2906
- [View$1]: getPicks$2,
2907
- [WorkspaceSymbol$1]: getPicks$1
2951
+ const commandMap = {
2952
+ 'QuickPick.addMenuEntries': add,
2953
+ 'QuickPick.close': close,
2954
+ 'QuickPick.create2': create,
2955
+ 'QuickPick.diff2': diff2,
2956
+ 'QuickPick.dispose': dispose,
2957
+ 'QuickPick.focusFirst': wrapCommand(focusFirst),
2958
+ 'QuickPick.focusIndex': wrapCommand(focusIndex),
2959
+ 'QuickPick.focusLast': wrapCommand(focusLast),
2960
+ 'QuickPick.focusNext': wrapCommand(focusNext),
2961
+ 'QuickPick.focusPrevious': wrapCommand(focusPrevious),
2962
+ 'QuickPick.getCommandIds': getCommandIds,
2963
+ 'QuickPick.getKeyBindings': getKeyBindings,
2964
+ 'QuickPick.handleBeforeInput': wrapCommand(handleBeforeInput),
2965
+ 'QuickPick.handleBlur': wrapCommand(handleBlur),
2966
+ 'QuickPick.handleClickAt': wrapCommand(handleClickAt),
2967
+ 'QuickPick.handleFocus': wrapCommand(handleFocus),
2968
+ 'QuickPick.handleInput': wrapCommand(handleInput),
2969
+ 'QuickPick.handleWheel': wrapCommand(handleWheel),
2970
+ 'QuickPick.loadContent': wrapCommand(loadContent),
2971
+ 'QuickPick.render2': render2,
2972
+ 'QuickPick.renderEventListeners': renderEventListeners,
2973
+ 'QuickPick.selectCurrentIndex': wrapCommand(selectCurrentIndex),
2974
+ 'QuickPick.selectIndex': wrapCommand(selectIndex),
2975
+ 'QuickPick.selectItem': wrapCommand(selectItem),
2976
+ 'QuickPick.setDeltaY': wrapCommand(setDeltaY),
2977
+ 'QuickPick.setValue': wrapCommand(setValue)
2908
2978
  };
2909
2979
 
2910
2980
  const Memfs = 'memfs';
@@ -2968,8 +3038,6 @@ const searchModules = {
2968
3038
 
2969
3039
  const listen = async () => {
2970
3040
  register(searchModules);
2971
- registerSelect(selectPicks);
2972
- registerGetPick(getPicks);
2973
3041
  const rpc = await WebWorkerRpcClient.create({
2974
3042
  commandMap: commandMap
2975
3043
  });