From 27bd7e76a245397170ad618337cfc1dc49851061 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 19 May 2017 23:15:47 -0700 Subject: 3869 Clean up a few superficial things in Caleb's commit. --- html/edit/003-shortcuts.mu.html | 3472 ++++++++++++++++++---------------- html/edit/005-sandbox.mu.html | 1810 +++++++++--------- html/edit/007-sandbox-delete.mu.html | 12 +- html/edit/008-sandbox-edit.mu.html | 10 +- html/edit/009-sandbox-test.mu.html | 6 +- html/edit/010-sandbox-trace.mu.html | 2 +- html/edit/011-errors.mu.html | 6 +- html/edit/012-editor-undo.mu.html | 16 +- 8 files changed, 2731 insertions(+), 2603 deletions(-) (limited to 'html/edit') diff --git a/html/edit/003-shortcuts.mu.html b/html/edit/003-shortcuts.mu.html index 4d03527e..3ad4d89e 100644 --- a/html/edit/003-shortcuts.mu.html +++ b/html/edit/003-shortcuts.mu.html @@ -1057,13 +1057,13 @@ if ('onhashchange' in window) { 995 ¦ ¦ c2:char <- get *curr, value:offset 996 ¦ ¦ at-newline?:bool <- equal c2, 10/newline 997 ¦ ¦ break-if at-newline? - 998 ¦ ¦ curr:&:duplex-list:char <- before-previous-line curr, editor + 998 ¦ ¦ curr:&:duplex-list:char <- before-previous-line curr, editor 999 ¦ ¦ no-motion?:bool <- equal curr, old 1000 ¦ ¦ return-if no-motion? 1001 ¦ } 1002 ¦ { 1003 ¦ ¦ old <- copy curr -1004 ¦ ¦ curr <- before-previous-line curr, editor +1004 ¦ ¦ curr <- before-previous-line curr, editor 1005 ¦ ¦ no-motion?:bool <- equal curr, old 1006 ¦ ¦ return-if no-motion? 1007 ¦ } @@ -1281,7 +1281,7 @@ if ('onhashchange' in window) { 1219 ¦ break-if already-at-bottom? 1220 ¦ # scan to start of next line, then to right column or until end of line 1221 ¦ max:num <- subtract right, left -1222 ¦ next-line:&:duplex-list:char <- before-start-of-next-line before-cursor, max +1222 ¦ next-line:&:duplex-list:char <- before-start-of-next-line before-cursor, max 1223 ¦ { 1224 ¦ ¦ # already at end of buffer? try to scroll up (so we can see more 1225 ¦ ¦ # warnings or sandboxes below) @@ -1689,1676 +1689,1868 @@ if ('onhashchange' in window) { 1627 s:text <- new [123 1628 456] 1629 e:&:editor <- new-editor s, 0/left, 10/right -1630 # start on second line, press ctrl-u -1631 assume-console [ -1632 ¦ left-click 2, 2 -1633 ¦ press ctrl-u -1634 ] -1635 run [ -1636 ¦ editor-event-loop screen, console, e -1637 ] -1638 # cursor deletes to start of line -1639 screen-should-contain [ -1640 ¦ . . -1641 ¦ .123 . -1642 ¦ .6 . -1643 ¦ .╌╌╌╌╌╌╌╌╌╌. -1644 ¦ . . -1645 ] -1646 ] -1647 -1648 after <handle-special-character> [ -1649 { -1650 ¦ delete-to-start-of-line?:bool <- equal c, 21/ctrl-u -1651 ¦ break-unless delete-to-start-of-line? -1652 ¦ <delete-to-start-of-line-begin> -1653 ¦ deleted-cells:&:duplex-list:char <- delete-to-start-of-line editor -1654 ¦ <delete-to-start-of-line-end> -1655 ¦ return 1/go-render -1656 } -1657 ] -1658 -1659 def delete-to-start-of-line editor:&:editor -> result:&:duplex-list:char, editor:&:editor [ -1660 local-scope -1661 load-ingredients -1662 # compute range to delete -1663 init:&:duplex-list:char <- get *editor, data:offset -1664 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset -1665 start:&:duplex-list:char <- copy before-cursor -1666 end:&:duplex-list:char <- next before-cursor -1667 { -1668 ¦ at-start-of-text?:bool <- equal start, init -1669 ¦ break-if at-start-of-text? -1670 ¦ curr:char <- get *start, value:offset -1671 ¦ at-start-of-line?:bool <- equal curr, 10/newline -1672 ¦ break-if at-start-of-line? -1673 ¦ start <- prev start -1674 ¦ assert start, [delete-to-start-of-line tried to move before start of text] -1675 ¦ loop -1676 } -1677 # snip it out -1678 result:&:duplex-list:char <- next start -1679 remove-between start, end -1680 # adjust cursor -1681 before-cursor <- copy start -1682 *editor <- put *editor, before-cursor:offset, before-cursor -1683 left:num <- get *editor, left:offset -1684 *editor <- put *editor, cursor-column:offset, left -1685 ] -1686 -1687 scenario editor-deletes-to-start-of-line-with-ctrl-u-2 [ -1688 local-scope -1689 assume-screen 10/width, 5/height -1690 s:text <- new [123 -1691 456] -1692 e:&:editor <- new-editor s, 0/left, 10/right -1693 # start on first line (no newline before), press ctrl-u -1694 assume-console [ -1695 ¦ left-click 1, 2 -1696 ¦ press ctrl-u -1697 ] -1698 run [ -1699 ¦ editor-event-loop screen, console, e -1700 ] -1701 # cursor deletes to start of line -1702 screen-should-contain [ -1703 ¦ . . -1704 ¦ .3 . -1705 ¦ .456 . -1706 ¦ .╌╌╌╌╌╌╌╌╌╌. -1707 ¦ . . -1708 ] -1709 ] -1710 -1711 scenario editor-deletes-to-start-of-line-with-ctrl-u-3 [ -1712 local-scope -1713 assume-screen 10/width, 5/height -1714 s:text <- new [123 -1715 456] -1716 e:&:editor <- new-editor s, 0/left, 10/right -1717 # start past end of line, press ctrl-u -1718 assume-console [ -1719 ¦ left-click 1, 3 -1720 ¦ press ctrl-u -1721 ] -1722 run [ -1723 ¦ editor-event-loop screen, console, e -1724 ] -1725 # cursor deletes to start of line -1726 screen-should-contain [ -1727 ¦ . . -1728 ¦ . . -1729 ¦ .456 . -1730 ¦ .╌╌╌╌╌╌╌╌╌╌. -1731 ¦ . . -1732 ] -1733 ] -1734 -1735 scenario editor-deletes-to-start-of-final-line-with-ctrl-u [ -1736 local-scope -1737 assume-screen 10/width, 5/height -1738 s:text <- new [123 -1739 456] -1740 e:&:editor <- new-editor s, 0/left, 10/right -1741 # start past end of final line, press ctrl-u -1742 assume-console [ -1743 ¦ left-click 2, 3 -1744 ¦ press ctrl-u -1745 ] -1746 run [ -1747 ¦ editor-event-loop screen, console, e -1748 ] -1749 # cursor deletes to start of line -1750 screen-should-contain [ -1751 ¦ . . -1752 ¦ .123 . -1753 ¦ . . -1754 ¦ .╌╌╌╌╌╌╌╌╌╌. -1755 ¦ . . -1756 ] -1757 ] -1758 -1759 # ctrl-k - delete text from cursor to end of line (but not the newline) -1760 -1761 scenario editor-deletes-to-end-of-line-with-ctrl-k [ -1762 local-scope -1763 assume-screen 10/width, 5/height -1764 s:text <- new [123 -1765 456] -1766 e:&:editor <- new-editor s, 0/left, 10/right -1767 # start on first line, press ctrl-k -1768 assume-console [ -1769 ¦ left-click 1, 1 -1770 ¦ press ctrl-k -1771 ] -1772 run [ -1773 ¦ editor-event-loop screen, console, e -1774 ] -1775 # cursor deletes to end of line -1776 screen-should-contain [ -1777 ¦ . . -1778 ¦ .1 . -1779 ¦ .456 . -1780 ¦ .╌╌╌╌╌╌╌╌╌╌. -1781 ¦ . . -1782 ] +1630 editor-render screen, e +1631 $clear-trace +1632 # start on second line, press ctrl-u +1633 assume-console [ +1634 ¦ left-click 2, 2 +1635 ¦ press ctrl-u +1636 ] +1637 run [ +1638 ¦ editor-event-loop screen, console, e +1639 ] +1640 # cursor deletes to start of line +1641 screen-should-contain [ +1642 ¦ . . +1643 ¦ .123 . +1644 ¦ .6 . +1645 ¦ .╌╌╌╌╌╌╌╌╌╌. +1646 ¦ . . +1647 ] +1648 check-trace-count-for-label 10, [print-character] +1649 ] +1650 +1651 after <handle-special-character> [ +1652 { +1653 ¦ delete-to-start-of-line?:bool <- equal c, 21/ctrl-u +1654 ¦ break-unless delete-to-start-of-line? +1655 ¦ <delete-to-start-of-line-begin> +1656 ¦ deleted-cells:&:duplex-list:char <- delete-to-start-of-line editor +1657 ¦ <delete-to-start-of-line-end> +1658 ¦ go-render?:bool <- minimal-render-for-ctrl-u editor, screen +1659 ¦ return +1660 } +1661 ] +1662 +1663 def minimal-render-for-ctrl-u editor:&:editor, screen:&:screen -> go-render?:bool, screen:&:screen [ +1664 local-scope +1665 load-ingredients +1666 curr-row:num <- get *editor, cursor-row:offset +1667 curr-column:num <- get *editor, cursor-column:offset +1668 left:num <- get *editor, left:offset +1669 right:num <- get *editor, right:offset +1670 end:num <- subtract left, right +1671 # accumulate the current line as text and render it +1672 buf:&:buffer:char <- new-buffer 30 # accumulator for the text we need to render +1673 curr:&:duplex-list:char <- get *editor, before-cursor:offset +1674 i:num <- copy 0 +1675 { +1676 ¦ i <- add i, 1 +1677 ¦ # if we have a wrapped line, give up and render the whole screen +1678 ¦ wrap?:bool <- equal i, end +1679 ¦ return-if wrap?, 1/do-render +1680 ¦ curr <- next curr +1681 ¦ break-unless curr +1682 ¦ c:char <- get *curr, value:offset +1683 ¦ b:bool <- equal c, 10 +1684 ¦ break-if b +1685 ¦ buf <- append buf, c +1686 ¦ loop +1687 } +1688 curr-line:text <- buffer-to-array buf +1689 render-code screen, curr-line, curr-column, right, curr-row +1690 return 0/dont-render +1691 ] +1692 +1693 def delete-to-start-of-line editor:&:editor -> result:&:duplex-list:char, editor:&:editor [ +1694 local-scope +1695 load-ingredients +1696 # compute range to delete +1697 init:&:duplex-list:char <- get *editor, data:offset +1698 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset +1699 start:&:duplex-list:char <- copy before-cursor +1700 end:&:duplex-list:char <- next before-cursor +1701 { +1702 ¦ at-start-of-text?:bool <- equal start, init +1703 ¦ break-if at-start-of-text? +1704 ¦ curr:char <- get *start, value:offset +1705 ¦ at-start-of-line?:bool <- equal curr, 10/newline +1706 ¦ break-if at-start-of-line? +1707 ¦ start <- prev start +1708 ¦ assert start, [delete-to-start-of-line tried to move before start of text] +1709 ¦ loop +1710 } +1711 # snip it out +1712 result:&:duplex-list:char <- next start +1713 remove-between start, end +1714 # adjust cursor +1715 before-cursor <- copy start +1716 *editor <- put *editor, before-cursor:offset, before-cursor +1717 left:num <- get *editor, left:offset +1718 *editor <- put *editor, cursor-column:offset, left +1719 ] +1720 +1721 def render-code screen:&:screen, s:text, left:num, right:num, row:num -> row:num, screen:&:screen [ +1722 local-scope +1723 load-ingredients +1724 return-unless s +1725 color:num <- copy 7/white +1726 column:num <- copy left +1727 screen <- move-cursor screen, row, column +1728 screen-height:num <- screen-height screen +1729 i:num <- copy 0 +1730 len:num <- length *s +1731 { +1732 ¦ +next-character +1733 ¦ done?:bool <- greater-or-equal i, len +1734 ¦ break-if done? +1735 ¦ done? <- greater-or-equal row, screen-height +1736 ¦ break-if done? +1737 ¦ c:char <- index *s, i +1738 ¦ <character-c-received> +1739 ¦ { +1740 ¦ ¦ # newline? move to left rather than 0 +1741 ¦ ¦ newline?:bool <- equal c, 10/newline +1742 ¦ ¦ break-unless newline? +1743 ¦ ¦ # clear rest of line in this window +1744 ¦ ¦ { +1745 ¦ ¦ ¦ done?:bool <- greater-than column, right +1746 ¦ ¦ ¦ break-if done? +1747 ¦ ¦ ¦ space:char <- copy 32/space +1748 ¦ ¦ ¦ print screen, space +1749 ¦ ¦ ¦ column <- add column, 1 +1750 ¦ ¦ ¦ loop +1751 ¦ ¦ } +1752 ¦ ¦ row <- add row, 1 +1753 ¦ ¦ column <- copy left +1754 ¦ ¦ screen <- move-cursor screen, row, column +1755 ¦ ¦ i <- add i, 1 +1756 ¦ ¦ loop +next-character +1757 ¦ } +1758 ¦ { +1759 ¦ ¦ # at right? wrap. +1760 ¦ ¦ at-right?:bool <- equal column, right +1761 ¦ ¦ break-unless at-right? +1762 ¦ ¦ # print wrap icon +1763 ¦ ¦ wrap-icon:char <- copy 8617/loop-back-to-left +1764 ¦ ¦ print screen, wrap-icon, 245/grey +1765 ¦ ¦ column <- copy left +1766 ¦ ¦ row <- add row, 1 +1767 ¦ ¦ screen <- move-cursor screen, row, column +1768 ¦ ¦ # don't increment i +1769 ¦ ¦ loop +next-character +1770 ¦ } +1771 ¦ i <- add i, 1 +1772 ¦ print screen, c, color +1773 ¦ column <- add column, 1 +1774 ¦ loop +1775 } +1776 was-at-left?:bool <- equal column, left +1777 clear-line-until screen, right +1778 { +1779 ¦ break-if was-at-left? +1780 ¦ row <- add row, 1 +1781 } +1782 move-cursor screen, row, left 1783 ] 1784 -1785 after <handle-special-character> [ -1786 { -1787 ¦ delete-to-end-of-line?:bool <- equal c, 11/ctrl-k -1788 ¦ break-unless delete-to-end-of-line? -1789 ¦ <delete-to-end-of-line-begin> -1790 ¦ deleted-cells:&:duplex-list:char <- delete-to-end-of-line editor -1791 ¦ <delete-to-end-of-line-end> -1792 ¦ return 1/go-render -1793 } -1794 ] -1795 -1796 def delete-to-end-of-line editor:&:editor -> result:&:duplex-list:char, editor:&:editor [ -1797 local-scope -1798 load-ingredients -1799 # compute range to delete -1800 start:&:duplex-list:char <- get *editor, before-cursor:offset -1801 end:&:duplex-list:char <- next start -1802 { -1803 ¦ at-end-of-text?:bool <- equal end, 0/null -1804 ¦ break-if at-end-of-text? -1805 ¦ curr:char <- get *end, value:offset -1806 ¦ at-end-of-line?:bool <- equal curr, 10/newline -1807 ¦ break-if at-end-of-line? -1808 ¦ end <- next end -1809 ¦ loop -1810 } -1811 # snip it out -1812 result <- next start -1813 remove-between start, end -1814 ] -1815 -1816 scenario editor-deletes-to-end-of-line-with-ctrl-k-2 [ -1817 local-scope -1818 assume-screen 10/width, 5/height -1819 s:text <- new [123 -1820 456] -1821 e:&:editor <- new-editor s, 0/left, 10/right -1822 # start on second line (no newline after), press ctrl-k -1823 assume-console [ -1824 ¦ left-click 2, 1 -1825 ¦ press ctrl-k -1826 ] -1827 run [ -1828 ¦ editor-event-loop screen, console, e -1829 ] -1830 # cursor deletes to end of line -1831 screen-should-contain [ -1832 ¦ . . -1833 ¦ .123 . -1834 ¦ .4 . -1835 ¦ .╌╌╌╌╌╌╌╌╌╌. -1836 ¦ . . -1837 ] -1838 ] -1839 -1840 scenario editor-deletes-to-end-of-line-with-ctrl-k-3 [ -1841 local-scope -1842 assume-screen 10/width, 5/height -1843 s:text <- new [123 -1844 456] -1845 e:&:editor <- new-editor s, 0/left, 10/right -1846 # start at end of line -1847 assume-console [ -1848 ¦ left-click 1, 2 -1849 ¦ press ctrl-k -1850 ] -1851 run [ -1852 ¦ editor-event-loop screen, console, e -1853 ] -1854 # cursor deletes just last character -1855 screen-should-contain [ -1856 ¦ . . -1857 ¦ .12 . -1858 ¦ .456 . -1859 ¦ .╌╌╌╌╌╌╌╌╌╌. -1860 ¦ . . -1861 ] -1862 ] -1863 -1864 scenario editor-deletes-to-end-of-line-with-ctrl-k-4 [ -1865 local-scope -1866 assume-screen 10/width, 5/height -1867 s:text <- new [123 -1868 456] -1869 e:&:editor <- new-editor s, 0/left, 10/right -1870 # start past end of line -1871 assume-console [ -1872 ¦ left-click 1, 3 -1873 ¦ press ctrl-k -1874 ] -1875 run [ -1876 ¦ editor-event-loop screen, console, e -1877 ] -1878 # cursor deletes nothing -1879 screen-should-contain [ -1880 ¦ . . -1881 ¦ .123 . -1882 ¦ .456 . -1883 ¦ .╌╌╌╌╌╌╌╌╌╌. -1884 ¦ . . -1885 ] -1886 ] -1887 -1888 scenario editor-deletes-to-end-of-line-with-ctrl-k-5 [ -1889 local-scope -1890 assume-screen 10/width, 5/height -1891 s:text <- new [123 -1892 456] -1893 e:&:editor <- new-editor s, 0/left, 10/right -1894 # start at end of text -1895 assume-console [ -1896 ¦ left-click 2, 2 -1897 ¦ press ctrl-k -1898 ] -1899 run [ -1900 ¦ editor-event-loop screen, console, e -1901 ] -1902 # cursor deletes just the final character -1903 screen-should-contain [ -1904 ¦ . . -1905 ¦ .123 . -1906 ¦ .45 . -1907 ¦ .╌╌╌╌╌╌╌╌╌╌. -1908 ¦ . . -1909 ] -1910 ] -1911 -1912 scenario editor-deletes-to-end-of-line-with-ctrl-k-6 [ -1913 local-scope -1914 assume-screen 10/width, 5/height -1915 s:text <- new [123 -1916 456] -1917 e:&:editor <- new-editor s, 0/left, 10/right -1918 # start past end of text -1919 assume-console [ -1920 ¦ left-click 2, 3 -1921 ¦ press ctrl-k -1922 ] -1923 run [ -1924 ¦ editor-event-loop screen, console, e -1925 ] -1926 # cursor deletes nothing -1927 screen-should-contain [ -1928 ¦ . . -1929 ¦ .123 . -1930 ¦ .456 . -1931 ¦ .╌╌╌╌╌╌╌╌╌╌. -1932 ¦ . . -1933 ] -1934 ] -1935 -1936 # cursor-down can scroll if necessary -1937 -1938 scenario editor-can-scroll-down-using-arrow-keys [ -1939 local-scope -1940 # screen has 1 line for menu + 3 lines -1941 assume-screen 10/width, 4/height -1942 # initialize editor with >3 lines -1943 s:text <- new [a -1944 b -1945 c -1946 d] -1947 e:&:editor <- new-editor s, 0/left, 10/right -1948 editor-render screen, e -1949 screen-should-contain [ -1950 ¦ . . -1951 ¦ .a . -1952 ¦ .b . -1953 ¦ .c . -1954 ] -1955 # position cursor at last line, then try to move further down -1956 assume-console [ -1957 ¦ left-click 3, 0 -1958 ¦ press down-arrow -1959 ] -1960 run [ -1961 ¦ editor-event-loop screen, console, e -1962 ] -1963 # screen slides by one line -1964 screen-should-contain [ -1965 ¦ . . -1966 ¦ .b . -1967 ¦ .c . -1968 ¦ .d . -1969 ] -1970 ] -1971 -1972 after <scroll-down> [ -1973 trace 10, [app], [scroll down] -1974 top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset -1975 left:num <- get *editor, left:offset -1976 right:num <- get *editor, right:offset -1977 max:num <- subtract right, left -1978 old-top:&:duplex-list:char <- copy top-of-screen -1979 top-of-screen <- before-start-of-next-line top-of-screen, max -1980 *editor <- put *editor, top-of-screen:offset, top-of-screen -1981 no-movement?:bool <- equal old-top, top-of-screen -1982 return-if no-movement?, 0/don't-render -1983 ] -1984 -1985 # takes a pointer into the doubly-linked list, scans ahead at most 'max' -1986 # positions until the next newline -1987 # beware: never return null pointer. -1988 def before-start-of-next-line original:&:duplex-list:char, max:num -> curr:&:duplex-list:char [ -1989 local-scope -1990 load-ingredients -1991 count:num <- copy 0 -1992 curr:&:duplex-list:char <- copy original -1993 # skip the initial newline if it exists -1994 { -1995 ¦ c:char <- get *curr, value:offset -1996 ¦ at-newline?:bool <- equal c, 10/newline -1997 ¦ break-unless at-newline? -1998 ¦ curr <- next curr -1999 ¦ count <- add count, 1 -2000 } -2001 { -2002 ¦ return-unless curr, original -2003 ¦ done?:bool <- greater-or-equal count, max -2004 ¦ break-if done? -2005 ¦ c:char <- get *curr, value:offset -2006 ¦ at-newline?:bool <- equal c, 10/newline -2007 ¦ break-if at-newline? -2008 ¦ curr <- next curr -2009 ¦ count <- add count, 1 -2010 ¦ loop -2011 } -2012 return-unless curr, original -2013 return curr -2014 ] -2015 -2016 scenario editor-scrolls-down-past-wrapped-line-using-arrow-keys [ -2017 local-scope -2018 # screen has 1 line for menu + 3 lines -2019 assume-screen 10/width, 4/height -2020 # initialize editor with a long, wrapped line and more than a screen of -2021 # other lines -2022 s:text <- new [abcdef -2023 g -2024 h -2025 i] -2026 e:&:editor <- new-editor s, 0/left, 5/right -2027 editor-render screen, e -2028 screen-should-contain [ -2029 ¦ . . -2030 ¦ .abcd↩ . -2031 ¦ .ef . -2032 ¦ .g . +1785 scenario editor-deletes-to-start-of-line-with-ctrl-u-2 [ +1786 local-scope +1787 assume-screen 10/width, 5/height +1788 s:text <- new [123 +1789 456] +1790 e:&:editor <- new-editor s, 0/left, 10/right +1791 editor-render screen, e +1792 $clear-trace +1793 # start on first line (no newline before), press ctrl-u +1794 assume-console [ +1795 ¦ left-click 1, 2 +1796 ¦ press ctrl-u +1797 ] +1798 run [ +1799 ¦ editor-event-loop screen, console, e +1800 ] +1801 # cursor deletes to start of line +1802 screen-should-contain [ +1803 ¦ . . +1804 ¦ .3 . +1805 ¦ .456 . +1806 ¦ .╌╌╌╌╌╌╌╌╌╌. +1807 ¦ . . +1808 ] +1809 check-trace-count-for-label 10, [print-character] +1810 ] +1811 +1812 scenario editor-deletes-to-start-of-line-with-ctrl-u-3 [ +1813 local-scope +1814 assume-screen 10/width, 5/height +1815 s:text <- new [123 +1816 456] +1817 e:&:editor <- new-editor s, 0/left, 10/right +1818 editor-render screen, e +1819 $clear-trace +1820 # start past end of line, press ctrl-u +1821 assume-console [ +1822 ¦ left-click 1, 3 +1823 ¦ press ctrl-u +1824 ] +1825 run [ +1826 ¦ editor-event-loop screen, console, e +1827 ] +1828 # cursor deletes to start of line +1829 screen-should-contain [ +1830 ¦ . . +1831 ¦ . . +1832 ¦ .456 . +1833 ¦ .╌╌╌╌╌╌╌╌╌╌. +1834 ¦ . . +1835 ] +1836 check-trace-count-for-label 10, [print-character] +1837 ] +1838 +1839 scenario editor-deletes-to-start-of-final-line-with-ctrl-u [ +1840 local-scope +1841 assume-screen 10/width, 5/height +1842 s:text <- new [123 +1843 456] +1844 e:&:editor <- new-editor s, 0/left, 10/right +1845 editor-render screen, e +1846 $clear-trace +1847 # start past end of final line, press ctrl-u +1848 assume-console [ +1849 ¦ left-click 2, 3 +1850 ¦ press ctrl-u +1851 ] +1852 run [ +1853 ¦ editor-event-loop screen, console, e +1854 ] +1855 # cursor deletes to start of line +1856 screen-should-contain [ +1857 ¦ . . +1858 ¦ .123 . +1859 ¦ . . +1860 ¦ .╌╌╌╌╌╌╌╌╌╌. +1861 ¦ . . +1862 ] +1863 check-trace-count-for-label 10, [print-character] +1864 ] +1865 +1866 # ctrl-k - delete text from cursor to end of line (but not the newline) +1867 +1868 scenario editor-deletes-to-end-of-line-with-ctrl-k [ +1869 local-scope +1870 assume-screen 10/width, 5/height +1871 s:text <- new [123 +1872 456] +1873 e:&:editor <- new-editor s, 0/left, 10/right +1874 editor-render screen, e +1875 $clear-trace +1876 # start on first line, press ctrl-k +1877 assume-console [ +1878 ¦ left-click 1, 1 +1879 ¦ press ctrl-k +1880 ] +1881 run [ +1882 ¦ editor-event-loop screen, console, e +1883 ] +1884 # cursor deletes to end of line +1885 screen-should-contain [ +1886 ¦ . . +1887 ¦ .1 . +1888 ¦ .456 . +1889 ¦ .╌╌╌╌╌╌╌╌╌╌. +1890 ¦ . . +1891 ] +1892 check-trace-count-for-label 9, [print-character] +1893 ] +1894 +1895 after <handle-special-character> [ +1896 { +1897 ¦ delete-to-end-of-line?:bool <- equal c, 11/ctrl-k +1898 ¦ break-unless delete-to-end-of-line? +1899 ¦ <delete-to-end-of-line-begin> +1900 ¦ deleted-cells:&:duplex-list:char <- delete-to-end-of-line editor +1901 ¦ <delete-to-end-of-line-end> +1902 ¦ # checks if we can do a minimal render and if we can it will do a minimal render +1903 ¦ go-render?:bool <- minimal-render-for-ctrl-k editor, screen, deleted-cells +1904 ¦ return +1905 } +1906 ] +1907 +1908 def minimal-render-for-ctrl-k editor:&:editor, screen:&:screen, deleted-cells:&:duplex-list:char -> go-render?:bool, screen:&:screen [ +1909 local-scope +1910 load-ingredients +1911 # if we deleted nothing, there's nothing to render +1912 return-unless deleted-cells, 0/dont-render +1913 # if we have a wrapped line, give up and render the whole screen +1914 curr-column:num <- get *editor, cursor-column:offset +1915 num-deleted-cells:num <- length, deleted-cells +1916 old-row-len:num <- add curr-column, num-deleted-cells +1917 left:num <- get *editor, left:offset +1918 right:num <- get *editor, right:offset +1919 end:num <- subtract right, left +1920 wrap?:bool <- greater-or-equal old-row-len, end +1921 return-if wrap?, 1/do-render +1922 # accumulate the current line as text and render it +1923 buf:&:buffer:char <- new-buffer 30 # accumulator for the text we need to render +1924 curr:&:duplex-list:char <- get *editor, before-cursor:offset +1925 i:num <- copy 0 +1926 { +1927 ¦ i <- add i, 1 +1928 ¦ # check if we are at the end of the line +1929 ¦ curr <- next curr +1930 ¦ break-unless curr +1931 ¦ c:char <- get *curr, value:offset +1932 ¦ # check if we have a newline +1933 ¦ b:bool <- equal c, 10 +1934 ¦ break-if b +1935 ¦ buf <- append buf, c +1936 ¦ loop +1937 } +1938 curr-line:text <- buffer-to-array buf +1939 curr-row:num <- get *editor, cursor-row:offset +1940 render-code screen, curr-line, curr-column, right, curr-row +1941 return 0/dont-render +1942 ] +1943 +1944 def delete-to-end-of-line editor:&:editor -> result:&:duplex-list:char, editor:&:editor [ +1945 local-scope +1946 load-ingredients +1947 # compute range to delete +1948 start:&:duplex-list:char <- get *editor, before-cursor:offset +1949 end:&:duplex-list:char <- next start +1950 { +1951 ¦ at-end-of-text?:bool <- equal end, 0/null +1952 ¦ break-if at-end-of-text? +1953 ¦ curr:char <- get *end, value:offset +1954 ¦ at-end-of-line?:bool <- equal curr, 10/newline +1955 ¦ break-if at-end-of-line? +1956 ¦ end <- next end +1957 ¦ loop +1958 } +1959 # snip it out +1960 result <- next start +1961 remove-between start, end +1962 ] +1963 +1964 scenario editor-deletes-to-end-of-line-with-ctrl-k-2 [ +1965 local-scope +1966 assume-screen 10/width, 5/height +1967 s:text <- new [123 +1968 456] +1969 e:&:editor <- new-editor s, 0/left, 10/right +1970 editor-render screen, e +1971 $clear-trace +1972 # start on second line (no newline after), press ctrl-k +1973 assume-console [ +1974 ¦ left-click 2, 1 +1975 ¦ press ctrl-k +1976 ] +1977 run [ +1978 ¦ editor-event-loop screen, console, e +1979 ] +1980 # cursor deletes to end of line +1981 screen-should-contain [ +1982 ¦ . . +1983 ¦ .123 . +1984 ¦ .4 . +1985 ¦ .╌╌╌╌╌╌╌╌╌╌. +1986 ¦ . . +1987 ] +1988 check-trace-count-for-label 9, [print-character] +1989 ] +1990 +1991 scenario editor-deletes-to-end-of-line-with-ctrl-k-3 [ +1992 local-scope +1993 assume-screen 10/width, 5/height +1994 s:text <- new [123 +1995 456] +1996 e:&:editor <- new-editor s, 0/left, 10/right +1997 editor-render screen, e +1998 $clear-trace +1999 # start at end of line +2000 assume-console [ +2001 ¦ left-click 1, 2 +2002 ¦ press ctrl-k +2003 ] +2004 run [ +2005 ¦ editor-event-loop screen, console, e +2006 ] +2007 # cursor deletes just last character +2008 screen-should-contain [ +2009 ¦ . . +2010 ¦ .12 . +2011 ¦ .456 . +2012 ¦ .╌╌╌╌╌╌╌╌╌╌. +2013 ¦ . . +2014 ] +2015 check-trace-count-for-label 8, [print-character] +2016 ] +2017 +2018 scenario editor-deletes-to-end-of-line-with-ctrl-k-4 [ +2019 local-scope +2020 assume-screen 10/width, 5/height +2021 s:text <- new [123 +2022 456] +2023 e:&:editor <- new-editor s, 0/left, 10/right +2024 editor-render screen, e +2025 $clear-trace +2026 # start past end of line +2027 assume-console [ +2028 ¦ left-click 1, 3 +2029 ¦ press ctrl-k +2030 ] +2031 run [ +2032 ¦ editor-event-loop screen, console, e 2033 ] -2034 # position cursor at last line, then try to move further down -2035 assume-console [ -2036 ¦ left-click 3, 0 -2037 ¦ press down-arrow -2038 ] -2039 run [ -2040 ¦ editor-event-loop screen, console, e +2034 # cursor deletes nothing +2035 screen-should-contain [ +2036 ¦ . . +2037 ¦ .123 . +2038 ¦ .456 . +2039 ¦ .╌╌╌╌╌╌╌╌╌╌. +2040 ¦ . . 2041 ] -2042 # screen shows partial wrapped line -2043 screen-should-contain [ -2044 ¦ . . -2045 ¦ .ef . -2046 ¦ .g . -2047 ¦ .h . -2048 ] -2049 ] -2050 -2051 scenario editor-scrolls-down-past-wrapped-line-using-arrow-keys-2 [ -2052 local-scope -2053 # screen has 1 line for menu + 3 lines -2054 assume-screen 10/width, 4/height -2055 # editor starts with a long line wrapping twice -2056 s:text <- new [abcdefghij -2057 k -2058 l -2059 m] -2060 e:&:editor <- new-editor s, 0/left, 5/right -2061 # position cursor at last line, then try to move further down -2062 assume-console [ -2063 ¦ left-click 3, 0 -2064 ¦ press down-arrow -2065 ] -2066 run [ -2067 ¦ editor-event-loop screen, console, e +2042 check-trace-count-for-label 7, [print-character] +2043 ] +2044 +2045 scenario editor-deletes-to-end-of-line-with-ctrl-k-5 [ +2046 local-scope +2047 assume-screen 10/width, 5/height +2048 s:text <- new [123 +2049 456] +2050 e:&:editor <- new-editor s, 0/left, 10/right +2051 editor-render screen, e +2052 $clear-trace +2053 # start at end of text +2054 assume-console [ +2055 ¦ left-click 2, 2 +2056 ¦ press ctrl-k +2057 ] +2058 run [ +2059 ¦ editor-event-loop screen, console, e +2060 ] +2061 # cursor deletes just the final character +2062 screen-should-contain [ +2063 ¦ . . +2064 ¦ .123 . +2065 ¦ .45 . +2066 ¦ .╌╌╌╌╌╌╌╌╌╌. +2067 ¦ . . 2068 ] -2069 # screen shows partial wrapped line containing a wrap icon -2070 screen-should-contain [ -2071 ¦ . . -2072 ¦ .efgh↩ . -2073 ¦ .ij . -2074 ¦ .k . -2075 ] -2076 # scroll down again -2077 assume-console [ -2078 ¦ press down-arrow -2079 ] -2080 run [ -2081 ¦ editor-event-loop screen, console, e -2082 ] -2083 # screen shows partial wrapped line -2084 screen-should-contain [ -2085 ¦ . . -2086 ¦ .ij . -2087 ¦ .k . -2088 ¦ .l . -2089 ] -2090 ] -2091 -2092 scenario editor-scrolls-down-when-line-wraps [ -2093 local-scope -2094 # screen has 1 line for menu + 3 lines -2095 assume-screen 5/width, 4/height -2096 # editor contains a long line in the third line -2097 s:text <- new [a -2098 b -2099 cdef] -2100 e:&:editor <- new-editor s, 0/left, 5/right -2101 # position cursor at end, type a character -2102 assume-console [ -2103 ¦ left-click 3, 4 -2104 ¦ type [g] -2105 ] -2106 run [ -2107 ¦ editor-event-loop screen, console, e -2108 ¦ 3:num/raw <- get *e, cursor-row:offset -2109 ¦ 4:num/raw <- get *e, cursor-column:offset -2110 ] -2111 # screen scrolls -2112 screen-should-contain [ -2113 ¦ . . -2114 ¦ .b . -2115 ¦ .cdef↩. -2116 ¦ .g . -2117 ] -2118 memory-should-contain [ -2119 ¦ 3 <- 3 -2120 ¦ 4 <- 1 -2121 ] -2122 ] -2123 -2124 scenario editor-scrolls-down-on-newline [ -2125 local-scope -2126 assume-screen 5/width, 4/height -2127 # position cursor after last line and type newline -2128 s:text <- new [a -2129 b -2130 c] -2131 e:&:editor <- new-editor s, 0/left, 5/right -2132 assume-console [ -2133 ¦ left-click 3, 4 -2134 ¦ type [ -2135 ] -2136 ] -2137 run [ -2138 ¦ editor-event-loop screen, console, e -2139 ¦ 3:num/raw <- get *e, cursor-row:offset -2140 ¦ 4:num/raw <- get *e, cursor-column:offset -2141 ] -2142 # screen scrolls -2143 screen-should-contain [ -2144 ¦ . . -2145 ¦ .b . -2146 ¦ .c . -2147 ¦ . . -2148 ] -2149 memory-should-contain [ -2150 ¦ 3 <- 3 -2151 ¦ 4 <- 0 -2152 ] -2153 ] -2154 -2155 scenario editor-scrolls-down-on-right-arrow [ -2156 local-scope -2157 # screen has 1 line for menu + 3 lines -2158 assume-screen 5/width, 4/height -2159 # editor contains a wrapped line -2160 s:text <- new [a -2161 b -2162 cdefgh] -2163 e:&:editor <- new-editor s, 0/left, 5/right -2164 # position cursor at end of screen and try to move right -2165 assume-console [ -2166 ¦ left-click 3, 3 -2167 ¦ press right-arrow -2168 ] -2169 run [ -2170 ¦ editor-event-loop screen, console, e -2171 ¦ 3:num/raw <- get *e, cursor-row:offset -2172 ¦ 4:num/raw <- get *e, cursor-column:offset -2173 ] -2174 # screen scrolls -2175 screen-should-contain [ -2176 ¦ . . -2177 ¦ .b . -2178 ¦ .cdef↩. -2179 ¦ .gh . -2180 ] -2181 memory-should-contain [ -2182 ¦ 3 <- 3 -2183 ¦ 4 <- 0 -2184 ] -2185 ] -2186 -2187 scenario editor-scrolls-down-on-right-arrow-2 [ -2188 local-scope -2189 # screen has 1 line for menu + 3 lines -2190 assume-screen 5/width, 4/height -2191 # editor contains more lines than can fit on screen -2192 s:text <- new [a -2193 b -2194 c -2195 d] -2196 e:&:editor <- new-editor s, 0/left, 5/right -2197 # position cursor at end of screen and try to move right -2198 assume-console [ -2199 ¦ left-click 3, 3 -2200 ¦ press right-arrow -2201 ] -2202 run [ -2203 ¦ editor-event-loop screen, console, e -2204 ¦ 3:num/raw <- get *e, cursor-row:offset -2205 ¦ 4:num/raw <- get *e, cursor-column:offset -2206 ] -2207 # screen scrolls -2208 screen-should-contain [ -2209 ¦ . . -2210 ¦ .b . -2211 ¦ .c . -2212 ¦ .d . -2213 ] -2214 memory-should-contain [ -2215 ¦ 3 <- 3 -2216 ¦ 4 <- 0 -2217 ] -2218 ] -2219 -2220 scenario editor-scrolls-at-end-on-down-arrow [ -2221 local-scope -2222 assume-screen 10/width, 5/height -2223 s:text <- new [abc -2224 de] -2225 e:&:editor <- new-editor s, 0/left, 10/right -2226 editor-render screen, e -2227 $clear-trace -2228 # try to move down past end of text -2229 assume-console [ -2230 ¦ left-click 2, 0 -2231 ¦ press down-arrow -2232 ] -2233 run [ -2234 ¦ editor-event-loop screen, console, e -2235 ¦ 3:num/raw <- get *e, cursor-row:offset -2236 ¦ 4:num/raw <- get *e, cursor-column:offset -2237 ] -2238 # screen should scroll, moving cursor to end of text -2239 memory-should-contain [ -2240 ¦ 3 <- 1 -2241 ¦ 4 <- 2 -2242 ] -2243 assume-console [ -2244 ¦ type [0] -2245 ] -2246 run [ -2247 ¦ editor-event-loop screen, console, e -2248 ] -2249 screen-should-contain [ -2250 ¦ . . -2251 ¦ .de0 . -2252 ¦ .╌╌╌╌╌╌╌╌╌╌. -2253 ¦ . . -2254 ] -2255 # try to move down again -2256 $clear-trace -2257 assume-console [ -2258 ¦ left-click 2, 0 -2259 ¦ press down-arrow +2069 check-trace-count-for-label 8, [print-character] +2070 ] +2071 +2072 scenario editor-deletes-to-end-of-line-with-ctrl-k-6 [ +2073 local-scope +2074 assume-screen 10/width, 5/height +2075 s:text <- new [123 +2076 456] +2077 e:&:editor <- new-editor s, 0/left, 10/right +2078 editor-render screen, e +2079 $clear-trace +2080 # start past end of text +2081 assume-console [ +2082 ¦ left-click 2, 3 +2083 ¦ press ctrl-k +2084 ] +2085 run [ +2086 ¦ editor-event-loop screen, console, e +2087 ] +2088 # cursor deletes nothing +2089 screen-should-contain [ +2090 ¦ . . +2091 ¦ .123 . +2092 ¦ .456 . +2093 ¦ .╌╌╌╌╌╌╌╌╌╌. +2094 ¦ . . +2095 ] +2096 # no prints necessary +2097 check-trace-count-for-label 0, [print-character] +2098 ] +2099 +2100 scenario editor-deletes-to-end-of-wrapped-line-with-ctrl-k [ +2101 local-scope +2102 assume-screen 10/width, 5/height +2103 # create an editor with the first line wrapping to a second screen row +2104 s:text <- new [1234 +2105 567] +2106 e:&:editor <- new-editor s, 0/left, 4/right +2107 editor-render screen, e +2108 $clear-trace +2109 # delete all of the first wrapped line +2110 assume-console [ +2111 ¦ press ctrl-k +2112 ] +2113 run [ +2114 ¦ editor-event-loop screen, console, e +2115 ] +2116 # screen shows an empty unwrapped first line +2117 screen-should-contain [ +2118 ¦ . . +2119 ¦ . . +2120 ¦ .567 . +2121 ¦ .╌╌╌╌ . +2122 ¦ . . +2123 ] +2124 # entire screen is refreshed +2125 check-trace-count-for-label 16, [print-character] +2126 ] +2127 +2128 # cursor-down can scroll if necessary +2129 +2130 scenario editor-can-scroll-down-using-arrow-keys [ +2131 local-scope +2132 # screen has 1 line for menu + 3 lines +2133 assume-screen 10/width, 4/height +2134 # initialize editor with >3 lines +2135 s:text <- new [a +2136 b +2137 c +2138 d] +2139 e:&:editor <- new-editor s, 0/left, 10/right +2140 editor-render screen, e +2141 screen-should-contain [ +2142 ¦ . . +2143 ¦ .a . +2144 ¦ .b . +2145 ¦ .c . +2146 ] +2147 # position cursor at last line, then try to move further down +2148 assume-console [ +2149 ¦ left-click 3, 0 +2150 ¦ press down-arrow +2151 ] +2152 run [ +2153 ¦ editor-event-loop screen, console, e +2154 ] +2155 # screen slides by one line +2156 screen-should-contain [ +2157 ¦ . . +2158 ¦ .b . +2159 ¦ .c . +2160 ¦ .d . +2161 ] +2162 ] +2163 +2164 after <scroll-down> [ +2165 trace 10, [app], [scroll down] +2166 top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset +2167 left:num <- get *editor, left:offset +2168 right:num <- get *editor, right:offset +2169 max:num <- subtract right, left +2170 old-top:&:duplex-list:char <- copy top-of-screen +2171 top-of-screen <- before-start-of-next-line top-of-screen, max +2172 *editor <- put *editor, top-of-screen:offset, top-of-screen +2173 no-movement?:bool <- equal old-top, top-of-screen +2174 return-if no-movement?, 0/don't-render +2175 ] +2176 +2177 # takes a pointer into the doubly-linked list, scans ahead at most 'max' +2178 # positions until the next newline +2179 # beware: never return null pointer. +2180 def before-start-of-next-line original:&:duplex-list:char, max:num -> curr:&:duplex-list:char [ +2181 local-scope +2182 load-ingredients +2183 count:num <- copy 0 +2184 curr:&:duplex-list:char <- copy original +2185 # skip the initial newline if it exists +2186 { +2187 ¦ c:char <- get *curr, value:offset +2188 ¦ at-newline?:bool <- equal c, 10/newline +2189 ¦ break-unless at-newline? +2190 ¦ curr <- next curr +2191 ¦ count <- add count, 1 +2192 } +2193 { +2194 ¦ return-unless curr, original +2195 ¦ done?:bool <- greater-or-equal count, max +2196 ¦ break-if done? +2197 ¦ c:char <- get *curr, value:offset +2198 ¦ at-newline?:bool <- equal c, 10/newline +2199 ¦ break-if at-newline? +2200 ¦ curr <- next curr +2201 ¦ count <- add count, 1 +2202 ¦ loop +2203 } +2204 return-unless curr, original +2205 return curr +2206 ] +2207 +2208 scenario editor-scrolls-down-past-wrapped-line-using-arrow-keys [ +2209 local-scope +2210 # screen has 1 line for menu + 3 lines +2211 assume-screen 10/width, 4/height +2212 # initialize editor with a long, wrapped line and more than a screen of +2213 # other lines +2214 s:text <- new [abcdef +2215 g +2216 h +2217 i] +2218 e:&:editor <- new-editor s, 0/left, 5/right +2219 editor-render screen, e +2220 screen-should-contain [ +2221 ¦ . . +2222 ¦ .abcd↩ . +2223 ¦ .ef . +2224 ¦ .g . +2225 ] +2226 # position cursor at last line, then try to move further down +2227 assume-console [ +2228 ¦ left-click 3, 0 +2229 ¦ press down-arrow +2230 ] +2231 run [ +2232 ¦ editor-event-loop screen, console, e +2233 ] +2234 # screen shows partial wrapped line +2235 screen-should-contain [ +2236 ¦ . . +2237 ¦ .ef . +2238 ¦ .g . +2239 ¦ .h . +2240 ] +2241 ] +2242 +2243 scenario editor-scrolls-down-past-wrapped-line-using-arrow-keys-2 [ +2244 local-scope +2245 # screen has 1 line for menu + 3 lines +2246 assume-screen 10/width, 4/height +2247 # editor starts with a long line wrapping twice +2248 s:text <- new [abcdefghij +2249 k +2250 l +2251 m] +2252 e:&:editor <- new-editor s, 0/left, 5/right +2253 # position cursor at last line, then try to move further down +2254 assume-console [ +2255 ¦ left-click 3, 0 +2256 ¦ press down-arrow +2257 ] +2258 run [ +2259 ¦ editor-event-loop screen, console, e 2260 ] -2261 run [ -2262 ¦ editor-event-loop screen, console, e -2263 ¦ 3:num/raw <- get *e, cursor-row:offset -2264 ¦ 4:num/raw <- get *e, cursor-column:offset -2265 ] -2266 # screen stops scrolling because cursor is already at top -2267 memory-should-contain [ -2268 ¦ 3 <- 1 -2269 ¦ 4 <- 3 -2270 ] -2271 check-trace-count-for-label 0, [print-character] -2272 assume-console [ -2273 ¦ type [1] +2261 # screen shows partial wrapped line containing a wrap icon +2262 screen-should-contain [ +2263 ¦ . . +2264 ¦ .efgh↩ . +2265 ¦ .ij . +2266 ¦ .k . +2267 ] +2268 # scroll down again +2269 assume-console [ +2270 ¦ press down-arrow +2271 ] +2272 run [ +2273 ¦ editor-event-loop screen, console, e 2274 ] -2275 run [ -2276 ¦ editor-event-loop screen, console, e -2277 ] -2278 screen-should-contain [ -2279 ¦ . . -2280 ¦ .de01 . -2281 ¦ .╌╌╌╌╌╌╌╌╌╌. -2282 ¦ . . -2283 ] -2284 ] -2285 -2286 scenario editor-combines-page-and-line-scroll [ -2287 local-scope -2288 # screen has 1 line for menu + 3 lines -2289 assume-screen 10/width, 4/height -2290 # initialize editor with a few pages of lines -2291 s:text <- new [a -2292 b -2293 c -2294 d -2295 e -2296 f -2297 g] -2298 e:&:editor <- new-editor s, 0/left, 5/right -2299 editor-render screen, e -2300 # scroll down one page and one line -2301 assume-console [ -2302 ¦ press page-down -2303 ¦ left-click 3, 0 -2304 ¦ press down-arrow -2305 ] -2306 run [ -2307 ¦ editor-event-loop screen, console, e -2308 ] -2309 # screen scrolls down 3 lines -2310 screen-should-contain [ -2311 ¦ . . -2312 ¦ .d . -2313 ¦ .e . -2314 ¦ .f . -2315 ] -2316 ] -2317 -2318 # cursor-up can scroll if necessary -2319 -2320 scenario editor-can-scroll-up-using-arrow-keys [ -2321 local-scope -2322 # screen has 1 line for menu + 3 lines -2323 assume-screen 10/width, 4/height -2324 # initialize editor with >3 lines -2325 s:text <- new [a -2326 b -2327 c -2328 d] -2329 e:&:editor <- new-editor s, 0/left, 10/right -2330 editor-render screen, e -2331 screen-should-contain [ -2332 ¦ . . -2333 ¦ .a . -2334 ¦ .b . -2335 ¦ .c . -2336 ] -2337 # position cursor at top of second page, then try to move up -2338 assume-console [ -2339 ¦ press page-down -2340 ¦ press up-arrow -2341 ] -2342 run [ -2343 ¦ editor-event-loop screen, console, e +2275 # screen shows partial wrapped line +2276 screen-should-contain [ +2277 ¦ . . +2278 ¦ .ij . +2279 ¦ .k . +2280 ¦ .l . +2281 ] +2282 ] +2283 +2284 scenario editor-scrolls-down-when-line-wraps [ +2285 local-scope +2286 # screen has 1 line for menu + 3 lines +2287 assume-screen 5/width, 4/height +2288 # editor contains a long line in the third line +2289 s:text <- new [a +2290 b +2291 cdef] +2292 e:&:editor <- new-editor s, 0/left, 5/right +2293 # position cursor at end, type a character +2294 assume-console [ +2295 ¦ left-click 3, 4 +2296 ¦ type [g] +2297 ] +2298 run [ +2299 ¦ editor-event-loop screen, console, e +2300 ¦ 3:num/raw <- get *e, cursor-row:offset +2301 ¦ 4:num/raw <- get *e, cursor-column:offset +2302 ] +2303 # screen scrolls +2304 screen-should-contain [ +2305 ¦ . . +2306 ¦ .b . +2307 ¦ .cdef↩. +2308 ¦ .g . +2309 ] +2310 memory-should-contain [ +2311 ¦ 3 <- 3 +2312 ¦ 4 <- 1 +2313 ] +2314 ] +2315 +2316 scenario editor-scrolls-down-on-newline [ +2317 local-scope +2318 assume-screen 5/width, 4/height +2319 # position cursor after last line and type newline +2320 s:text <- new [a +2321 b +2322 c] +2323 e:&:editor <- new-editor s, 0/left, 5/right +2324 assume-console [ +2325 ¦ left-click 3, 4 +2326 ¦ type [ +2327 ] +2328 ] +2329 run [ +2330 ¦ editor-event-loop screen, console, e +2331 ¦ 3:num/raw <- get *e, cursor-row:offset +2332 ¦ 4:num/raw <- get *e, cursor-column:offset +2333 ] +2334 # screen scrolls +2335 screen-should-contain [ +2336 ¦ . . +2337 ¦ .b . +2338 ¦ .c . +2339 ¦ . . +2340 ] +2341 memory-should-contain [ +2342 ¦ 3 <- 3 +2343 ¦ 4 <- 0 2344 ] -2345 # screen slides by one line -2346 screen-should-contain [ -2347 ¦ . . -2348 ¦ .b . -2349 ¦ .c . -2350 ¦ .d . -2351 ] -2352 ] -2353 -2354 after <scroll-up> [ -2355 trace 10, [app], [scroll up] -2356 top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset -2357 old-top:&:duplex-list:char <- copy top-of-screen -2358 top-of-screen <- before-previous-line top-of-screen, editor -2359 *editor <- put *editor, top-of-screen:offset, top-of-screen -2360 no-movement?:bool <- equal old-top, top-of-screen -2361 return-if no-movement?, 0/don't-render -2362 ] -2363 -2364 # takes a pointer into the doubly-linked list, scans back to before start of -2365 # previous *wrapped* line -2366 # beware: never return null pointer -2367 def before-previous-line in:&:duplex-list:char, editor:&:editor -> out:&:duplex-list:char [ -2368 local-scope -2369 load-ingredients -2370 curr:&:duplex-list:char <- copy in -2371 c:char <- get *curr, value:offset -2372 # compute max, number of characters to skip -2373 # 1 + len%(width-1) -2374 # except rotate second term to vary from 1 to width-1 rather than 0 to width-2 -2375 left:num <- get *editor, left:offset -2376 right:num <- get *editor, right:offset -2377 max-line-length:num <- subtract right, left, -1/exclusive-right, 1/wrap-icon -2378 sentinel:&:duplex-list:char <- get *editor, data:offset -2379 len:num <- previous-line-length curr, sentinel -2380 { -2381 ¦ break-if len -2382 ¦ # empty line; just skip this newline -2383 ¦ prev:&:duplex-list:char <- prev curr -2384 ¦ return-unless prev, curr -2385 ¦ return prev -2386 } -2387 _, max:num <- divide-with-remainder len, max-line-length -2388 # remainder 0 => scan one width-worth -2389 { -2390 ¦ break-if max -2391 ¦ max <- copy max-line-length -2392 } -2393 max <- add max, 1 -2394 count:num <- copy 0 -2395 # skip 'max' characters -2396 { -2397 ¦ done?:bool <- greater-or-equal count, max -2398 ¦ break-if done? -2399 ¦ prev:&:duplex-list:char <- prev curr -2400 ¦ break-unless prev -2401 ¦ curr <- copy prev -2402 ¦ count <- add count, 1 -2403 ¦ loop -2404 } -2405 return curr -2406 ] -2407 -2408 scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys [ -2409 local-scope -2410 # screen has 1 line for menu + 3 lines -2411 assume-screen 10/width, 4/height -2412 # initialize editor with a long, wrapped line and more than a screen of -2413 # other lines -2414 s:text <- new [abcdef -2415 g -2416 h -2417 i] -2418 e:&:editor <- new-editor s, 0/left, 5/right -2419 editor-render screen, e -2420 screen-should-contain [ -2421 ¦ . . -2422 ¦ .abcd↩ . -2423 ¦ .ef . -2424 ¦ .g . -2425 ] -2426 # position cursor at top of second page, just below wrapped line -2427 assume-console [ -2428 ¦ press page-down +2345 ] +2346 +2347 scenario editor-scrolls-down-on-right-arrow [ +2348 local-scope +2349 # screen has 1 line for menu + 3 lines +2350 assume-screen 5/width, 4/height +2351 # editor contains a wrapped line +2352 s:text <- new [a +2353 b +2354 cdefgh] +2355 e:&:editor <- new-editor s, 0/left, 5/right +2356 # position cursor at end of screen and try to move right +2357 assume-console [ +2358 ¦ left-click 3, 3 +2359 ¦ press right-arrow +2360 ] +2361 run [ +2362 ¦ editor-event-loop screen, console, e +2363 ¦ 3:num/raw <- get *e, cursor-row:offset +2364 ¦ 4:num/raw <- get *e, cursor-column:offset +2365 ] +2366 # screen scrolls +2367 screen-should-contain [ +2368 ¦ . . +2369 ¦ .b . +2370 ¦ .cdef↩. +2371 ¦ .gh . +2372 ] +2373 memory-should-contain [ +2374 ¦ 3 <- 3 +2375 ¦ 4 <- 0 +2376 ] +2377 ] +2378 +2379 scenario editor-scrolls-down-on-right-arrow-2 [ +2380 local-scope +2381 # screen has 1 line for menu + 3 lines +2382 assume-screen 5/width, 4/height +2383 # editor contains more lines than can fit on screen +2384 s:text <- new [a +2385 b +2386 c +2387 d] +2388 e:&:editor <- new-editor s, 0/left, 5/right +2389 # position cursor at end of screen and try to move right +2390 assume-console [ +2391 ¦ left-click 3, 3 +2392 ¦ press right-arrow +2393 ] +2394 run [ +2395 ¦ editor-event-loop screen, console, e +2396 ¦ 3:num/raw <- get *e, cursor-row:offset +2397 ¦ 4:num/raw <- get *e, cursor-column:offset +2398 ] +2399 # screen scrolls +2400 screen-should-contain [ +2401 ¦ . . +2402 ¦ .b . +2403 ¦ .c . +2404 ¦ .d . +2405 ] +2406 memory-should-contain [ +2407 ¦ 3 <- 3 +2408 ¦ 4 <- 0 +2409 ] +2410 ] +2411 +2412 scenario editor-scrolls-at-end-on-down-arrow [ +2413 local-scope +2414 assume-screen 10/width, 5/height +2415 s:text <- new [abc +2416 de] +2417 e:&:editor <- new-editor s, 0/left, 10/right +2418 editor-render screen, e +2419 $clear-trace +2420 # try to move down past end of text +2421 assume-console [ +2422 ¦ left-click 2, 0 +2423 ¦ press down-arrow +2424 ] +2425 run [ +2426 ¦ editor-event-loop screen, console, e +2427 ¦ 3:num/raw <- get *e, cursor-row:offset +2428 ¦ 4:num/raw <- get *e, cursor-column:offset 2429 ] -2430 run [ -2431 ¦ editor-event-loop screen, console, e -2432 ] -2433 screen-should-contain [ -2434 ¦ . . -2435 ¦ .g . -2436 ¦ .h . -2437 ¦ .i . -2438 ] -2439 # now move up one line -2440 assume-console [ -2441 ¦ press up-arrow -2442 ] -2443 run [ -2444 ¦ editor-event-loop screen, console, e -2445 ] -2446 # screen shows partial wrapped line -2447 screen-should-contain [ -2448 ¦ . . -2449 ¦ .ef . -2450 ¦ .g . -2451 ¦ .h . +2430 # screen should scroll, moving cursor to end of text +2431 memory-should-contain [ +2432 ¦ 3 <- 1 +2433 ¦ 4 <- 2 +2434 ] +2435 assume-console [ +2436 ¦ type [0] +2437 ] +2438 run [ +2439 ¦ editor-event-loop screen, console, e +2440 ] +2441 screen-should-contain [ +2442 ¦ . . +2443 ¦ .de0 . +2444 ¦ .╌╌╌╌╌╌╌╌╌╌. +2445 ¦ . . +2446 ] +2447 # try to move down again +2448 $clear-trace +2449 assume-console [ +2450 ¦ left-click 2, 0 +2451 ¦ press down-arrow 2452 ] -2453 ] -2454 -2455 scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys-2 [ -2456 local-scope -2457 # screen has 1 line for menu + 4 lines -2458 assume-screen 10/width, 5/height -2459 # editor starts with a long line wrapping twice, occupying 3 of the 4 lines -2460 s:text <- new [abcdefghij -2461 k -2462 l -2463 m] -2464 e:&:editor <- new-editor s, 0/left, 5/right -2465 editor-render screen, e -2466 # position cursor at top of second page -2467 assume-console [ -2468 ¦ press page-down +2453 run [ +2454 ¦ editor-event-loop screen, console, e +2455 ¦ 3:num/raw <- get *e, cursor-row:offset +2456 ¦ 4:num/raw <- get *e, cursor-column:offset +2457 ] +2458 # screen stops scrolling because cursor is already at top +2459 memory-should-contain [ +2460 ¦ 3 <- 1 +2461 ¦ 4 <- 3 +2462 ] +2463 check-trace-count-for-label 0, [print-character] +2464 assume-console [ +2465 ¦ type [1] +2466 ] +2467 run [ +2468 ¦ editor-event-loop screen, console, e 2469 ] -2470 run [ -2471 ¦ editor-event-loop screen, console, e -2472 ] -2473 screen-should-contain [ +2470 screen-should-contain [ +2471 ¦ . . +2472 ¦ .de01 . +2473 ¦ .╌╌╌╌╌╌╌╌╌╌. 2474 ¦ . . -2475 ¦ .k . -2476 ¦ .l . -2477 ¦ .m . -2478 ¦ .╌╌╌╌╌ . -2479 ] -2480 # move up one line -2481 assume-console [ -2482 ¦ press up-arrow -2483 ] -2484 run [ -2485 ¦ editor-event-loop screen, console, e -2486 ] -2487 # screen shows partial wrapped line -2488 screen-should-contain [ -2489 ¦ . . -2490 ¦ .ij . -2491 ¦ .k . -2492 ¦ .l . -2493 ¦ .m . -2494 ] -2495 # move up a second line -2496 assume-console [ -2497 ¦ press up-arrow -2498 ] -2499 run [ -2500 ¦ editor-event-loop screen, console, e -2501 ] -2502 # screen shows partial wrapped line -2503 screen-should-contain [ -2504 ¦ . . -2505 ¦ .efgh↩ . -2506 ¦ .ij . -2507 ¦ .k . -2508 ¦ .l . -2509 ] -2510 # move up a third line -2511 assume-console [ -2512 ¦ press up-arrow -2513 ] -2514 run [ -2515 ¦ editor-event-loop screen, console, e -2516 ] -2517 # screen shows partial wrapped line -2518 screen-should-contain [ -2519 ¦ . . -2520 ¦ .abcd↩ . -2521 ¦ .efgh↩ . -2522 ¦ .ij . -2523 ¦ .k . -2524 ] -2525 ] -2526 -2527 # same as editor-scrolls-up-past-wrapped-line-using-arrow-keys but length -2528 # slightly off, just to prevent over-training -2529 scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys-3 [ -2530 local-scope -2531 # screen has 1 line for menu + 3 lines -2532 assume-screen 10/width, 4/height -2533 # initialize editor with a long, wrapped line and more than a screen of -2534 # other lines -2535 s:text <- new [abcdef -2536 g -2537 h -2538 i] -2539 e:&:editor <- new-editor s, 0/left, 6/right -2540 editor-render screen, e -2541 screen-should-contain [ -2542 ¦ . . -2543 ¦ .abcde↩ . -2544 ¦ .f . -2545 ¦ .g . -2546 ] -2547 # position cursor at top of second page, just below wrapped line -2548 assume-console [ -2549 ¦ press page-down -2550 ] -2551 run [ -2552 ¦ editor-event-loop screen, console, e -2553 ] -2554 screen-should-contain [ -2555 ¦ . . -2556 ¦ .g . -2557 ¦ .h . -2558 ¦ .i . -2559 ] -2560 # now move up one line -2561 assume-console [ -2562 ¦ press up-arrow -2563 ] -2564 run [ -2565 ¦ editor-event-loop screen, console, e -2566 ] -2567 # screen shows partial wrapped line -2568 screen-should-contain [ -2569 ¦ . . -2570 ¦ .f . -2571 ¦ .g . -2572 ¦ .h . -2573 ] -2574 ] -2575 -2576 # check empty lines -2577 scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys-4 [ -2578 local-scope -2579 assume-screen 10/width, 4/height -2580 # initialize editor with some lines around an empty line -2581 s:text <- new [a -2582 b -2583 -2584 c -2585 d -2586 e] -2587 e:&:editor <- new-editor s, 0/left, 6/right -2588 editor-render screen, e -2589 assume-console [ -2590 ¦ press page-down -2591 ] -2592 run [ -2593 ¦ editor-event-loop screen, console, e -2594 ] -2595 screen-should-contain [ -2596 ¦ . . -2597 ¦ . . -2598 ¦ .c . -2599 ¦ .d . -2600 ] -2601 assume-console [ -2602 ¦ press page-down -2603 ] -2604 run [ -2605 ¦ editor-event-loop screen, console, e -2606 ] -2607 screen-should-contain [ -2608 ¦ . . -2609 ¦ .d . -2610 ¦ .e . -2611 ¦ .╌╌╌╌╌╌ . -2612 ] -2613 assume-console [ -2614 ¦ press page-up -2615 ] -2616 run [ -2617 ¦ editor-event-loop screen, console, e -2618 ] -2619 screen-should-contain [ -2620 ¦ . . -2621 ¦ . . -2622 ¦ .c . -2623 ¦ .d . +2475 ] +2476 ] +2477 +2478 scenario editor-combines-page-and-line-scroll [ +2479 local-scope +2480 # screen has 1 line for menu + 3 lines +2481 assume-screen 10/width, 4/height +2482 # initialize editor with a few pages of lines +2483 s:text <- new [a +2484 b +2485 c +2486 d +2487 e +2488 f +2489 g] +2490 e:&:editor <- new-editor s, 0/left, 5/right +2491 editor-render screen, e +2492 # scroll down one page and one line +2493 assume-console [ +2494 ¦ press page-down +2495 ¦ left-click 3, 0 +2496 ¦ press down-arrow +2497 ] +2498 run [ +2499 ¦ editor-event-loop screen, console, e +2500 ] +2501 # screen scrolls down 3 lines +2502 screen-should-contain [ +2503 ¦ . . +2504 ¦ .d . +2505 ¦ .e . +2506 ¦ .f . +2507 ] +2508 ] +2509 +2510 # cursor-up can scroll if necessary +2511 +2512 scenario editor-can-scroll-up-using-arrow-keys [ +2513 local-scope +2514 # screen has 1 line for menu + 3 lines +2515 assume-screen 10/width, 4/height +2516 # initialize editor with >3 lines +2517 s:text <- new [a +2518 b +2519 c +2520 d] +2521 e:&:editor <- new-editor s, 0/left, 10/right +2522 editor-render screen, e +2523 screen-should-contain [ +2524 ¦ . . +2525 ¦ .a . +2526 ¦ .b . +2527 ¦ .c . +2528 ] +2529 # position cursor at top of second page, then try to move up +2530 assume-console [ +2531 ¦ press page-down +2532 ¦ press up-arrow +2533 ] +2534 run [ +2535 ¦ editor-event-loop screen, console, e +2536 ] +2537 # screen slides by one line +2538 screen-should-contain [ +2539 ¦ . . +2540 ¦ .b . +2541 ¦ .c . +2542 ¦ .d . +2543 ] +2544 ] +2545 +2546 after <scroll-up> [ +2547 trace 10, [app], [scroll up] +2548 top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset +2549 old-top:&:duplex-list:char <- copy top-of-screen +2550 top-of-screen <- before-previous-line top-of-screen, editor +2551 *editor <- put *editor, top-of-screen:offset, top-of-screen +2552 no-movement?:bool <- equal old-top, top-of-screen +2553 return-if no-movement?, 0/don't-render +2554 ] +2555 +2556 # takes a pointer into the doubly-linked list, scans back to before start of +2557 # previous *wrapped* line +2558 # beware: never return null pointer +2559 def before-previous-line in:&:duplex-list:char, editor:&:editor -> out:&:duplex-list:char [ +2560 local-scope +2561 load-ingredients +2562 curr:&:duplex-list:char <- copy in +2563 c:char <- get *curr, value:offset +2564 # compute max, number of characters to skip +2565 # 1 + len%(width-1) +2566 # except rotate second term to vary from 1 to width-1 rather than 0 to width-2 +2567 left:num <- get *editor, left:offset +2568 right:num <- get *editor, right:offset +2569 max-line-length:num <- subtract right, left, -1/exclusive-right, 1/wrap-icon +2570 sentinel:&:duplex-list:char <- get *editor, data:offset +2571 len:num <- previous-line-length curr, sentinel +2572 { +2573 ¦ break-if len +2574 ¦ # empty line; just skip this newline +2575 ¦ prev:&:duplex-list:char <- prev curr +2576 ¦ return-unless prev, curr +2577 ¦ return prev +2578 } +2579 _, max:num <- divide-with-remainder len, max-line-length +2580 # remainder 0 => scan one width-worth +2581 { +2582 ¦ break-if max +2583 ¦ max <- copy max-line-length +2584 } +2585 max <- add max, 1 +2586 count:num <- copy 0 +2587 # skip 'max' characters +2588 { +2589 ¦ done?:bool <- greater-or-equal count, max +2590 ¦ break-if done? +2591 ¦ prev:&:duplex-list:char <- prev curr +2592 ¦ break-unless prev +2593 ¦ curr <- copy prev +2594 ¦ count <- add count, 1 +2595 ¦ loop +2596 } +2597 return curr +2598 ] +2599 +2600 scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys [ +2601 local-scope +2602 # screen has 1 line for menu + 3 lines +2603 assume-screen 10/width, 4/height +2604 # initialize editor with a long, wrapped line and more than a screen of +2605 # other lines +2606 s:text <- new [abcdef +2607 g +2608 h +2609 i] +2610 e:&:editor <- new-editor s, 0/left, 5/right +2611 editor-render screen, e +2612 screen-should-contain [ +2613 ¦ . . +2614 ¦ .abcd↩ . +2615 ¦ .ef . +2616 ¦ .g . +2617 ] +2618 # position cursor at top of second page, just below wrapped line +2619 assume-console [ +2620 ¦ press page-down +2621 ] +2622 run [ +2623 ¦ editor-event-loop screen, console, e 2624 ] -2625 ] -2626 -2627 scenario editor-scrolls-up-on-left-arrow [ -2628 local-scope -2629 # screen has 1 line for menu + 3 lines -2630 assume-screen 5/width, 4/height -2631 # editor contains >3 lines -2632 s:text <- new [a -2633 b -2634 c -2635 d -2636 e] -2637 e:&:editor <- new-editor s, 0/left, 5/right -2638 editor-render screen, e -2639 # position cursor at top of second page -2640 assume-console [ -2641 ¦ press page-down -2642 ] -2643 run [ -2644 ¦ editor-event-loop screen, console, e -2645 ] -2646 screen-should-contain [ -2647 ¦ . . -2648 ¦ .c . -2649 ¦ .d . -2650 ¦ .e . -2651 ] -2652 # now try to move left -2653 assume-console [ -2654 ¦ press left-arrow -2655 ] -2656 run [ -2657 ¦ editor-event-loop screen, console, e -2658 ¦ 3:num/raw <- get *e, cursor-row:offset -2659 ¦ 4:num/raw <- get *e, cursor-column:offset -2660 ] -2661 # screen scrolls -2662 screen-should-contain [ -2663 ¦ . . -2664 ¦ .b . -2665 ¦ .c . -2666 ¦ .d . -2667 ] -2668 memory-should-contain [ -2669 ¦ 3 <- 1 -2670 ¦ 4 <- 1 +2625 screen-should-contain [ +2626 ¦ . . +2627 ¦ .g . +2628 ¦ .h . +2629 ¦ .i . +2630 ] +2631 # now move up one line +2632 assume-console [ +2633 ¦ press up-arrow +2634 ] +2635 run [ +2636 ¦ editor-event-loop screen, console, e +2637 ] +2638 # screen shows partial wrapped line +2639 screen-should-contain [ +2640 ¦ . . +2641 ¦ .ef . +2642 ¦ .g . +2643 ¦ .h . +2644 ] +2645 ] +2646 +2647 scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys-2 [ +2648 local-scope +2649 # screen has 1 line for menu + 4 lines +2650 assume-screen 10/width, 5/height +2651 # editor starts with a long line wrapping twice, occupying 3 of the 4 lines +2652 s:text <- new [abcdefghij +2653 k +2654 l +2655 m] +2656 e:&:editor <- new-editor s, 0/left, 5/right +2657 editor-render screen, e +2658 # position cursor at top of second page +2659 assume-console [ +2660 ¦ press page-down +2661 ] +2662 run [ +2663 ¦ editor-event-loop screen, console, e +2664 ] +2665 screen-should-contain [ +2666 ¦ . . +2667 ¦ .k . +2668 ¦ .l . +2669 ¦ .m . +2670 ¦ .╌╌╌╌╌ . 2671 ] -2672 ] -2673 -2674 scenario editor-can-scroll-up-to-start-of-file [ -2675 local-scope -2676 # screen has 1 line for menu + 3 lines -2677 assume-screen 10/width, 4/height -2678 # initialize editor with >3 lines -2679 s:text <- new [a -2680 b -2681 c -2682 d] -2683 e:&:editor <- new-editor s, 0/left, 10/right -2684 editor-render screen, e -2685 screen-should-contain [ -2686 ¦ . . -2687 ¦ .a . -2688 ¦ .b . -2689 ¦ .c . +2672 # move up one line +2673 assume-console [ +2674 ¦ press up-arrow +2675 ] +2676 run [ +2677 ¦ editor-event-loop screen, console, e +2678 ] +2679 # screen shows partial wrapped line +2680 screen-should-contain [ +2681 ¦ . . +2682 ¦ .ij . +2683 ¦ .k . +2684 ¦ .l . +2685 ¦ .m . +2686 ] +2687 # move up a second line +2688 assume-console [ +2689 ¦ press up-arrow 2690 ] -2691 # position cursor at top of second page, then try to move up to start of -2692 # text -2693 assume-console [ -2694 ¦ press page-down -2695 ¦ press up-arrow -2696 ¦ press up-arrow -2697 ] -2698 run [ -2699 ¦ editor-event-loop screen, console, e -2700 ] -2701 # screen slides by one line -2702 screen-should-contain [ -2703 ¦ . . -2704 ¦ .a . -2705 ¦ .b . -2706 ¦ .c . -2707 ] -2708 # try to move up again -2709 assume-console [ -2710 ¦ press up-arrow -2711 ] -2712 run [ -2713 ¦ editor-event-loop screen, console, e -2714 ] -2715 # screen remains unchanged -2716 screen-should-contain [ -2717 ¦ . . -2718 ¦ .a . -2719 ¦ .b . -2720 ¦ .c . -2721 ] -2722 ] -2723 -2724 # ctrl-f/page-down - render next page if it exists -2725 -2726 scenario editor-can-scroll [ -2727 local-scope -2728 assume-screen 10/width, 4/height -2729 s:text <- new [a -2730 b -2731 c -2732 d] -2733 e:&:editor <- new-editor s, 0/left, 10/right -2734 editor-render screen, e -2735 screen-should-contain [ -2736 ¦ . . -2737 ¦ .a . -2738 ¦ .b . -2739 ¦ .c . -2740 ] -2741 # scroll down -2742 assume-console [ -2743 ¦ press page-down -2744 ] -2745 run [ -2746 ¦ editor-event-loop screen, console, e -2747 ] -2748 # screen shows next page -2749 screen-should-contain [ -2750 ¦ . . -2751 ¦ .c . -2752 ¦ .d . -2753 ¦ .╌╌╌╌╌╌╌╌╌╌. -2754 ] -2755 ] -2756 -2757 after <handle-special-character> [ -2758 { -2759 ¦ page-down?:bool <- equal c, 6/ctrl-f -2760 ¦ break-unless page-down? -2761 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset -2762 ¦ <move-cursor-begin> -2763 ¦ page-down editor -2764 ¦ undo-coalesce-tag:num <- copy 0/never -2765 ¦ <move-cursor-end> -2766 ¦ top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset -2767 ¦ movement?:bool <- not-equal top-of-screen, old-top -2768 ¦ return movement?/go-render -2769 } -2770 ] -2771 -2772 after <handle-special-key> [ -2773 { -2774 ¦ page-down?:bool <- equal k, 65518/page-down -2775 ¦ break-unless page-down? -2776 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset -2777 ¦ <move-cursor-begin> -2778 ¦ page-down editor -2779 ¦ undo-coalesce-tag:num <- copy 0/never -2780 ¦ <move-cursor-end> -2781 ¦ top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset -2782 ¦ movement?:bool <- not-equal top-of-screen, old-top -2783 ¦ return movement?/go-render -2784 } -2785 ] -2786 -2787 # page-down skips entire wrapped lines, so it can't scroll past lines -2788 # taking up the entire screen -2789 def page-down editor:&:editor -> editor:&:editor [ -2790 local-scope -2791 load-ingredients -2792 # if editor contents don't overflow screen, do nothing -2793 bottom-of-screen:&:duplex-list:char <- get *editor, bottom-of-screen:offset -2794 return-unless bottom-of-screen -2795 # if not, position cursor at final character -2796 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset -2797 before-cursor:&:duplex-list:char <- prev bottom-of-screen -2798 *editor <- put *editor, before-cursor:offset, before-cursor -2799 # keep one line in common with previous page -2800 { -2801 ¦ last:char <- get *before-cursor, value:offset -2802 ¦ newline?:bool <- equal last, 10/newline -2803 ¦ break-unless newline?:bool -2804 ¦ before-cursor <- prev before-cursor -2805 ¦ *editor <- put *editor, before-cursor:offset, before-cursor -2806 } -2807 # move cursor and top-of-screen to start of that line -2808 move-to-start-of-line editor -2809 before-cursor <- get *editor, before-cursor:offset -2810 *editor <- put *editor, top-of-screen:offset, before-cursor -2811 ] -2812 -2813 scenario editor-does-not-scroll-past-end [ -2814 local-scope -2815 assume-screen 10/width, 4/height -2816 s:text <- new [a -2817 b] -2818 e:&:editor <- new-editor s, 0/left, 10/right -2819 editor-render screen, e -2820 screen-should-contain [ -2821 ¦ . . -2822 ¦ .a . -2823 ¦ .b . -2824 ¦ .╌╌╌╌╌╌╌╌╌╌. -2825 ] -2826 # scroll down -2827 assume-console [ -2828 ¦ press page-down -2829 ] -2830 run [ -2831 ¦ editor-event-loop screen, console, e -2832 ] -2833 # screen remains unmodified -2834 screen-should-contain [ -2835 ¦ . . -2836 ¦ .a . -2837 ¦ .b . -2838 ¦ .╌╌╌╌╌╌╌╌╌╌. -2839 ] -2840 ] -2841 -2842 scenario editor-starts-next-page-at-start-of-wrapped-line [ -2843 local-scope -2844 # screen has 1 line for menu + 3 lines for text -2845 assume-screen 10/width, 4/height -2846 # editor contains a long last line -2847 s:text <- new [a -2848 b -2849 cdefgh] -2850 # editor screen triggers wrap of last line -2851 e:&:editor <- new-editor s, 0/left, 4/right -2852 editor-render screen, e -2853 # some part of last line is not displayed +2691 run [ +2692 ¦ editor-event-loop screen, console, e +2693 ] +2694 # screen shows partial wrapped line +2695 screen-should-contain [ +2696 ¦ . . +2697 ¦ .efgh↩ . +2698 ¦ .ij . +2699 ¦ .k . +2700 ¦ .l . +2701 ] +2702 # move up a third line +2703 assume-console [ +2704 ¦ press up-arrow +2705 ] +2706 run [ +2707 ¦ editor-event-loop screen, console, e +2708 ] +2709 # screen shows partial wrapped line +2710 screen-should-contain [ +2711 ¦ . . +2712 ¦ .abcd↩ . +2713 ¦ .efgh↩ . +2714 ¦ .ij . +2715 ¦ .k . +2716 ] +2717 ] +2718 +2719 # same as editor-scrolls-up-past-wrapped-line-using-arrow-keys but length +2720 # slightly off, just to prevent over-training +2721 scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys-3 [ +2722 local-scope +2723 # screen has 1 line for menu + 3 lines +2724 assume-screen 10/width, 4/height +2725 # initialize editor with a long, wrapped line and more than a screen of +2726 # other lines +2727 s:text <- new [abcdef +2728 g +2729 h +2730 i] +2731 e:&:editor <- new-editor s, 0/left, 6/right +2732 editor-render screen, e +2733 screen-should-contain [ +2734 ¦ . . +2735 ¦ .abcde↩ . +2736 ¦ .f . +2737 ¦ .g . +2738 ] +2739 # position cursor at top of second page, just below wrapped line +2740 assume-console [ +2741 ¦ press page-down +2742 ] +2743 run [ +2744 ¦ editor-event-loop screen, console, e +2745 ] +2746 screen-should-contain [ +2747 ¦ . . +2748 ¦ .g . +2749 ¦ .h . +2750 ¦ .i . +2751 ] +2752 # now move up one line +2753 assume-console [ +2754 ¦ press up-arrow +2755 ] +2756 run [ +2757 ¦ editor-event-loop screen, console, e +2758 ] +2759 # screen shows partial wrapped line +2760 screen-should-contain [ +2761 ¦ . . +2762 ¦ .f . +2763 ¦ .g . +2764 ¦ .h . +2765 ] +2766 ] +2767 +2768 # check empty lines +2769 scenario editor-scrolls-up-past-wrapped-line-using-arrow-keys-4 [ +2770 local-scope +2771 assume-screen 10/width, 4/height +2772 # initialize editor with some lines around an empty line +2773 s:text <- new [a +2774 b +2775 +2776 c +2777 d +2778 e] +2779 e:&:editor <- new-editor s, 0/left, 6/right +2780 editor-render screen, e +2781 assume-console [ +2782 ¦ press page-down +2783 ] +2784 run [ +2785 ¦ editor-event-loop screen, console, e +2786 ] +2787 screen-should-contain [ +2788 ¦ . . +2789 ¦ . . +2790 ¦ .c . +2791 ¦ .d . +2792 ] +2793 assume-console [ +2794 ¦ press page-down +2795 ] +2796 run [ +2797 ¦ editor-event-loop screen, console, e +2798 ] +2799 screen-should-contain [ +2800 ¦ . . +2801 ¦ .d . +2802 ¦ .e . +2803 ¦ .╌╌╌╌╌╌ . +2804 ] +2805 assume-console [ +2806 ¦ press page-up +2807 ] +2808 run [ +2809 ¦ editor-event-loop screen, console, e +2810 ] +2811 screen-should-contain [ +2812 ¦ . . +2813 ¦ . . +2814 ¦ .c . +2815 ¦ .d . +2816 ] +2817 ] +2818 +2819 scenario editor-scrolls-up-on-left-arrow [ +2820 local-scope +2821 # screen has 1 line for menu + 3 lines +2822 assume-screen 5/width, 4/height +2823 # editor contains >3 lines +2824 s:text <- new [a +2825 b +2826 c +2827 d +2828 e] +2829 e:&:editor <- new-editor s, 0/left, 5/right +2830 editor-render screen, e +2831 # position cursor at top of second page +2832 assume-console [ +2833 ¦ press page-down +2834 ] +2835 run [ +2836 ¦ editor-event-loop screen, console, e +2837 ] +2838 screen-should-contain [ +2839 ¦ . . +2840 ¦ .c . +2841 ¦ .d . +2842 ¦ .e . +2843 ] +2844 # now try to move left +2845 assume-console [ +2846 ¦ press left-arrow +2847 ] +2848 run [ +2849 ¦ editor-event-loop screen, console, e +2850 ¦ 3:num/raw <- get *e, cursor-row:offset +2851 ¦ 4:num/raw <- get *e, cursor-column:offset +2852 ] +2853 # screen scrolls 2854 screen-should-contain [ -2855 ¦ . . -2856 ¦ .a . -2857 ¦ .b . -2858 ¦ .cde↩ . +2855 ¦ . . +2856 ¦ .b . +2857 ¦ .c . +2858 ¦ .d . 2859 ] -2860 # scroll down -2861 assume-console [ -2862 ¦ press page-down +2860 memory-should-contain [ +2861 ¦ 3 <- 1 +2862 ¦ 4 <- 1 2863 ] -2864 run [ -2865 ¦ editor-event-loop screen, console, e -2866 ] -2867 # screen shows entire wrapped line -2868 screen-should-contain [ -2869 ¦ . . -2870 ¦ .cde↩ . -2871 ¦ .fgh . -2872 ¦ .╌╌╌╌ . -2873 ] -2874 ] -2875 -2876 scenario editor-starts-next-page-at-start-of-wrapped-line-2 [ -2877 local-scope -2878 # screen has 1 line for menu + 3 lines for text -2879 assume-screen 10/width, 4/height -2880 # editor contains a very long line that occupies last two lines of screen -2881 # and still has something left over -2882 s:text <- new [a -2883 bcdefgh] -2884 e:&:editor <- new-editor s, 0/left, 4/right -2885 editor-render screen, e -2886 # some part of last line is not displayed -2887 screen-should-contain [ -2888 ¦ . . -2889 ¦ .a . -2890 ¦ .bcd↩ . -2891 ¦ .efg↩ . +2864 ] +2865 +2866 scenario editor-can-scroll-up-to-start-of-file [ +2867 local-scope +2868 # screen has 1 line for menu + 3 lines +2869 assume-screen 10/width, 4/height +2870 # initialize editor with >3 lines +2871 s:text <- new [a +2872 b +2873 c +2874 d] +2875 e:&:editor <- new-editor s, 0/left, 10/right +2876 editor-render screen, e +2877 screen-should-contain [ +2878 ¦ . . +2879 ¦ .a . +2880 ¦ .b . +2881 ¦ .c . +2882 ] +2883 # position cursor at top of second page, then try to move up to start of +2884 # text +2885 assume-console [ +2886 ¦ press page-down +2887 ¦ press up-arrow +2888 ¦ press up-arrow +2889 ] +2890 run [ +2891 ¦ editor-event-loop screen, console, e 2892 ] -2893 # scroll down -2894 assume-console [ -2895 ¦ press page-down -2896 ] -2897 run [ -2898 ¦ editor-event-loop screen, console, e +2893 # screen slides by one line +2894 screen-should-contain [ +2895 ¦ . . +2896 ¦ .a . +2897 ¦ .b . +2898 ¦ .c . 2899 ] -2900 # screen shows entire wrapped line -2901 screen-should-contain [ -2902 ¦ . . -2903 ¦ .bcd↩ . -2904 ¦ .efg↩ . -2905 ¦ .h . +2900 # try to move up again +2901 assume-console [ +2902 ¦ press up-arrow +2903 ] +2904 run [ +2905 ¦ editor-event-loop screen, console, e 2906 ] -2907 ] -2908 -2909 # ctrl-b/page-up - render previous page if it exists -2910 -2911 scenario editor-can-scroll-up [ -2912 local-scope -2913 assume-screen 10/width, 4/height -2914 s:text <- new [a -2915 b -2916 c -2917 d] -2918 e:&:editor <- new-editor s, 0/left, 10/right -2919 editor-render screen, e -2920 screen-should-contain [ -2921 ¦ . . -2922 ¦ .a . -2923 ¦ .b . -2924 ¦ .c . -2925 ] -2926 # scroll down -2927 assume-console [ -2928 ¦ press page-down -2929 ] -2930 run [ -2931 ¦ editor-event-loop screen, console, e +2907 # screen remains unchanged +2908 screen-should-contain [ +2909 ¦ . . +2910 ¦ .a . +2911 ¦ .b . +2912 ¦ .c . +2913 ] +2914 ] +2915 +2916 # ctrl-f/page-down - render next page if it exists +2917 +2918 scenario editor-can-scroll [ +2919 local-scope +2920 assume-screen 10/width, 4/height +2921 s:text <- new [a +2922 b +2923 c +2924 d] +2925 e:&:editor <- new-editor s, 0/left, 10/right +2926 editor-render screen, e +2927 screen-should-contain [ +2928 ¦ . . +2929 ¦ .a . +2930 ¦ .b . +2931 ¦ .c . 2932 ] -2933 # screen shows next page -2934 screen-should-contain [ -2935 ¦ . . -2936 ¦ .c . -2937 ¦ .d . -2938 ¦ .╌╌╌╌╌╌╌╌╌╌. +2933 # scroll down +2934 assume-console [ +2935 ¦ press page-down +2936 ] +2937 run [ +2938 ¦ editor-event-loop screen, console, e 2939 ] -2940 # scroll back up -2941 assume-console [ -2942 ¦ press page-up -2943 ] -2944 run [ -2945 ¦ editor-event-loop screen, console, e +2940 # screen shows next page +2941 screen-should-contain [ +2942 ¦ . . +2943 ¦ .c . +2944 ¦ .d . +2945 ¦ .╌╌╌╌╌╌╌╌╌╌. 2946 ] -2947 # screen shows original page again -2948 screen-should-contain [ -2949 ¦ . . -2950 ¦ .a . -2951 ¦ .b . -2952 ¦ .c . -2953 ] -2954 ] -2955 -2956 after <handle-special-character> [ -2957 { -2958 ¦ page-up?:bool <- equal c, 2/ctrl-b -2959 ¦ break-unless page-up? -2960 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset -2961 ¦ <move-cursor-begin> -2962 ¦ editor <- page-up editor, screen-height -2963 ¦ undo-coalesce-tag:num <- copy 0/never -2964 ¦ <move-cursor-end> -2965 ¦ top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset -2966 ¦ movement?:bool <- not-equal top-of-screen, old-top -2967 ¦ return movement?/go-render -2968 } -2969 ] -2970 -2971 after <handle-special-key> [ -2972 { -2973 ¦ page-up?:bool <- equal k, 65519/page-up -2974 ¦ break-unless page-up? -2975 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset -2976 ¦ <move-cursor-begin> -2977 ¦ editor <- page-up editor, screen-height -2978 ¦ undo-coalesce-tag:num <- copy 0/never -2979 ¦ <move-cursor-end> -2980 ¦ top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset -2981 ¦ movement?:bool <- not-equal top-of-screen, old-top -2982 ¦ # don't bother re-rendering if nothing changed. todo: test this -2983 ¦ return movement?/go-render -2984 } -2985 ] -2986 -2987 def page-up editor:&:editor, screen-height:num -> editor:&:editor [ -2988 local-scope -2989 load-ingredients -2990 max:num <- subtract screen-height, 1/menu-bar, 1/overlapping-line -2991 count:num <- copy 0 -2992 top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset -2993 { -2994 ¦ done?:bool <- greater-or-equal count, max -2995 ¦ break-if done? -2996 ¦ prev:&:duplex-list:char <- before-previous-line top-of-screen, editor -2997 ¦ break-unless prev -2998 ¦ top-of-screen <- copy prev -2999 ¦ *editor <- put *editor, top-of-screen:offset, top-of-screen -3000 ¦ count <- add count, 1 -3001 ¦ loop -3002 } +2947 ] +2948 +2949 after <handle-special-character> [ +2950 { +2951 ¦ page-down?:bool <- equal c, 6/ctrl-f +2952 ¦ break-unless page-down? +2953 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset +2954 ¦ <move-cursor-begin> +2955 ¦ page-down editor +2956 ¦ undo-coalesce-tag:num <- copy 0/never +2957 ¦ <move-cursor-end> +2958 ¦ top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset +2959 ¦ movement?:bool <- not-equal top-of-screen, old-top +2960 ¦ return movement?/go-render +2961 } +2962 ] +2963 +2964 after <handle-special-key> [ +2965 { +2966 ¦ page-down?:bool <- equal k, 65518/page-down +2967 ¦ break-unless page-down? +2968 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset +2969 ¦ <move-cursor-begin> +2970 ¦ page-down editor +2971 ¦ undo-coalesce-tag:num <- copy 0/never +2972 ¦ <move-cursor-end> +2973 ¦ top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset +2974 ¦ movement?:bool <- not-equal top-of-screen, old-top +2975 ¦ return movement?/go-render +2976 } +2977 ] +2978 +2979 # page-down skips entire wrapped lines, so it can't scroll past lines +2980 # taking up the entire screen +2981 def page-down editor:&:editor -> editor:&:editor [ +2982 local-scope +2983 load-ingredients +2984 # if editor contents don't overflow screen, do nothing +2985 bottom-of-screen:&:duplex-list:char <- get *editor, bottom-of-screen:offset +2986 return-unless bottom-of-screen +2987 # if not, position cursor at final character +2988 before-cursor:&:duplex-list:char <- get *editor, before-cursor:offset +2989 before-cursor:&:duplex-list:char <- prev bottom-of-screen +2990 *editor <- put *editor, before-cursor:offset, before-cursor +2991 # keep one line in common with previous page +2992 { +2993 ¦ last:char <- get *before-cursor, value:offset +2994 ¦ newline?:bool <- equal last, 10/newline +2995 ¦ break-unless newline?:bool +2996 ¦ before-cursor <- prev before-cursor +2997 ¦ *editor <- put *editor, before-cursor:offset, before-cursor +2998 } +2999 # move cursor and top-of-screen to start of that line +3000 move-to-start-of-line editor +3001 before-cursor <- get *editor, before-cursor:offset +3002 *editor <- put *editor, top-of-screen:offset, before-cursor 3003 ] 3004 -3005 scenario editor-can-scroll-up-multiple-pages [ +3005 scenario editor-does-not-scroll-past-end [ 3006 local-scope -3007 # screen has 1 line for menu + 3 lines -3008 assume-screen 10/width, 4/height -3009 # initialize editor with 8 lines -3010 s:text <- new [a -3011 b -3012 c -3013 d -3014 e -3015 f -3016 g -3017 h] -3018 e:&:editor <- new-editor s, 0/left, 10/right -3019 editor-render screen, e -3020 screen-should-contain [ -3021 ¦ . . -3022 ¦ .a . -3023 ¦ .b . -3024 ¦ .c . -3025 ] -3026 # scroll down two pages -3027 assume-console [ -3028 ¦ press page-down -3029 ¦ press page-down -3030 ] -3031 run [ -3032 ¦ editor-event-loop screen, console, e -3033 ] -3034 # screen shows third page -3035 screen-should-contain [ -3036 ¦ . . -3037 ¦ .e . -3038 ¦ .f . -3039 ¦ .g . -3040 ] -3041 # scroll up -3042 assume-console [ -3043 ¦ press page-up -3044 ] -3045 run [ -3046 ¦ editor-event-loop screen, console, e -3047 ] -3048 # screen shows second page -3049 screen-should-contain [ -3050 ¦ . . -3051 ¦ .c . -3052 ¦ .d . -3053 ¦ .e . -3054 ] -3055 # scroll up again -3056 assume-console [ -3057 ¦ press page-up +3007 assume-screen 10/width, 4/height +3008 s:text <- new [a +3009 b] +3010 e:&:editor <- new-editor s, 0/left, 10/right +3011 editor-render screen, e +3012 screen-should-contain [ +3013 ¦ . . +3014 ¦ .a . +3015 ¦ .b . +3016 ¦ .╌╌╌╌╌╌╌╌╌╌. +3017 ] +3018 # scroll down +3019 assume-console [ +3020 ¦ press page-down +3021 ] +3022 run [ +3023 ¦ editor-event-loop screen, console, e +3024 ] +3025 # screen remains unmodified +3026 screen-should-contain [ +3027 ¦ . . +3028 ¦ .a . +3029 ¦ .b . +3030 ¦ .╌╌╌╌╌╌╌╌╌╌. +3031 ] +3032 ] +3033 +3034 scenario editor-starts-next-page-at-start-of-wrapped-line [ +3035 local-scope +3036 # screen has 1 line for menu + 3 lines for text +3037 assume-screen 10/width, 4/height +3038 # editor contains a long last line +3039 s:text <- new [a +3040 b +3041 cdefgh] +3042 # editor screen triggers wrap of last line +3043 e:&:editor <- new-editor s, 0/left, 4/right +3044 editor-render screen, e +3045 # some part of last line is not displayed +3046 screen-should-contain [ +3047 ¦ . . +3048 ¦ .a . +3049 ¦ .b . +3050 ¦ .cde↩ . +3051 ] +3052 # scroll down +3053 assume-console [ +3054 ¦ press page-down +3055 ] +3056 run [ +3057 ¦ editor-event-loop screen, console, e 3058 ] -3059 run [ -3060 ¦ editor-event-loop screen, console, e -3061 ] -3062 # screen shows original page again -3063 screen-should-contain [ -3064 ¦ . . -3065 ¦ .a . -3066 ¦ .b . -3067 ¦ .c . -3068 ] -3069 ] -3070 -3071 scenario editor-can-scroll-up-wrapped-lines [ -3072 local-scope -3073 # screen has 1 line for menu + 5 lines for text -3074 assume-screen 10/width, 6/height -3075 # editor contains a long line in the first page -3076 s:text <- new [a -3077 b -3078 cdefgh -3079 i -3080 j -3081 k -3082 l -3083 m -3084 n -3085 o] -3086 # editor screen triggers wrap of last line -3087 e:&:editor <- new-editor s, 0/left, 4/right -3088 editor-render screen, e -3089 # some part of last line is not displayed -3090 screen-should-contain [ -3091 ¦ . . -3092 ¦ .a . -3093 ¦ .b . -3094 ¦ .cde↩ . -3095 ¦ .fgh . -3096 ¦ .i . -3097 ] -3098 # scroll down a page and a line -3099 assume-console [ -3100 ¦ press page-down -3101 ¦ left-click 5, 0 -3102 ¦ press down-arrow -3103 ] -3104 run [ -3105 ¦ editor-event-loop screen, console, e -3106 ] -3107 # screen shows entire wrapped line -3108 screen-should-contain [ -3109 ¦ . . -3110 ¦ .j . -3111 ¦ .k . -3112 ¦ .l . -3113 ¦ .m . -3114 ¦ .n . -3115 ] -3116 # now scroll up one page -3117 assume-console [ -3118 ¦ press page-up -3119 ] -3120 run [ -3121 ¦ editor-event-loop screen, console, e -3122 ] -3123 # screen resets -3124 screen-should-contain [ -3125 ¦ . . -3126 ¦ .b . -3127 ¦ .cde↩ . -3128 ¦ .fgh . -3129 ¦ .i . -3130 ¦ .j . +3059 # screen shows entire wrapped line +3060 screen-should-contain [ +3061 ¦ . . +3062 ¦ .cde↩ . +3063 ¦ .fgh . +3064 ¦ .╌╌╌╌ . +3065 ] +3066 ] +3067 +3068 scenario editor-starts-next-page-at-start-of-wrapped-line-2 [ +3069 local-scope +3070 # screen has 1 line for menu + 3 lines for text +3071 assume-screen 10/width, 4/height +3072 # editor contains a very long line that occupies last two lines of screen +3073 # and still has something left over +3074 s:text <- new [a +3075 bcdefgh] +3076 e:&:editor <- new-editor s, 0/left, 4/right +3077 editor-render screen, e +3078 # some part of last line is not displayed +3079 screen-should-contain [ +3080 ¦ . . +3081 ¦ .a . +3082 ¦ .bcd↩ . +3083 ¦ .efg↩ . +3084 ] +3085 # scroll down +3086 assume-console [ +3087 ¦ press page-down +3088 ] +3089 run [ +3090 ¦ editor-event-loop screen, console, e +3091 ] +3092 # screen shows entire wrapped line +3093 screen-should-contain [ +3094 ¦ . . +3095 ¦ .bcd↩ . +3096 ¦ .efg↩ . +3097 ¦ .h . +3098 ] +3099 ] +3100 +3101 # ctrl-b/page-up - render previous page if it exists +3102 +3103 scenario editor-can-scroll-up [ +3104 local-scope +3105 assume-screen 10/width, 4/height +3106 s:text <- new [a +3107 b +3108 c +3109 d] +3110 e:&:editor <- new-editor s, 0/left, 10/right +3111 editor-render screen, e +3112 screen-should-contain [ +3113 ¦ . . +3114 ¦ .a . +3115 ¦ .b . +3116 ¦ .c . +3117 ] +3118 # scroll down +3119 assume-console [ +3120 ¦ press page-down +3121 ] +3122 run [ +3123 ¦ editor-event-loop screen, console, e +3124 ] +3125 # screen shows next page +3126 screen-should-contain [ +3127 ¦ . . +3128 ¦ .c . +3129 ¦ .d . +3130 ¦ .╌╌╌╌╌╌╌╌╌╌. 3131 ] -3132 ] -3133 -3134 scenario editor-can-scroll-up-wrapped-lines-2 [ -3135 local-scope -3136 # screen has 1 line for menu + 3 lines for text -3137 assume-screen 10/width, 4/height -3138 # editor contains a very long line that occupies last two lines of screen -3139 # and still has something left over -3140 s:text <- new [a -3141 bcdefgh] -3142 e:&:editor <- new-editor s, 0/left, 4/right -3143 editor-render screen, e -3144 # some part of last line is not displayed -3145 screen-should-contain [ -3146 ¦ . . -3147 ¦ .a . -3148 ¦ .bcd↩ . -3149 ¦ .efg↩ . -3150 ] -3151 # scroll down -3152 assume-console [ -3153 ¦ press page-down -3154 ] -3155 run [ -3156 ¦ editor-event-loop screen, console, e -3157 ] -3158 # screen shows entire wrapped line -3159 screen-should-contain [ -3160 ¦ . . -3161 ¦ .bcd↩ . -3162 ¦ .efg↩ . -3163 ¦ .h . -3164 ] -3165 # scroll back up -3166 assume-console [ -3167 ¦ press page-up -3168 ] -3169 run [ -3170 ¦ editor-event-loop screen, console, e -3171 ] -3172 # screen resets -3173 screen-should-contain [ -3174 ¦ . . -3175 ¦ .a . -3176 ¦ .bcd↩ . -3177 ¦ .efg↩ . -3178 ] -3179 ] -3180 -3181 scenario editor-can-scroll-up-past-nonempty-lines [ -3182 local-scope -3183 assume-screen 10/width, 4/height -3184 # text with empty line in second screen -3185 s:text <- new [axx -3186 bxx -3187 cxx -3188 dxx -3189 exx -3190 fxx -3191 gxx -3192 hxx -3193 ] -3194 e:&:editor <- new-editor s, 0/left, 4/right -3195 editor-render screen, e -3196 screen-should-contain [ -3197 ¦ . . -3198 ¦ .axx . -3199 ¦ .bxx . -3200 ¦ .cxx . -3201 ] -3202 assume-console [ -3203 ¦ press page-down -3204 ] -3205 run [ -3206 ¦ editor-event-loop screen, console, e -3207 ] -3208 screen-should-contain [ -3209 ¦ . . -3210 ¦ .cxx . -3211 ¦ .dxx . -3212 ¦ .exx . -3213 ] -3214 assume-console [ -3215 ¦ press page-down -3216 ] -3217 run [ -3218 ¦ editor-event-loop screen, console, e -3219 ] -3220 screen-should-contain [ -3221 ¦ . . -3222 ¦ .exx . -3223 ¦ .fxx . -3224 ¦ .gxx . +3132 # scroll back up +3133 assume-console [ +3134 ¦ press page-up +3135 ] +3136 run [ +3137 ¦ editor-event-loop screen, console, e +3138 ] +3139 # screen shows original page again +3140 screen-should-contain [ +3141 ¦ . . +3142 ¦ .a . +3143 ¦ .b . +3144 ¦ .c . +3145 ] +3146 ] +3147 +3148 after <handle-special-character> [ +3149 { +3150 ¦ page-up?:bool <- equal c, 2/ctrl-b +3151 ¦ break-unless page-up? +3152 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset +3153 ¦ <move-cursor-begin> +3154 ¦ editor <- page-up editor, screen-height +3155 ¦ undo-coalesce-tag:num <- copy 0/never +3156 ¦ <move-cursor-end> +3157 ¦ top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset +3158 ¦ movement?:bool <- not-equal top-of-screen, old-top +3159 ¦ return movement?/go-render +3160 } +3161 ] +3162 +3163 after <handle-special-key> [ +3164 { +3165 ¦ page-up?:bool <- equal k, 65519/page-up +3166 ¦ break-unless page-up? +3167 ¦ old-top:&:duplex-list:char <- get *editor, top-of-screen:offset +3168 ¦ <move-cursor-begin> +3169 ¦ editor <- page-up editor, screen-height +3170 ¦ undo-coalesce-tag:num <- copy 0/never +3171 ¦ <move-cursor-end> +3172 ¦ top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset +3173 ¦ movement?:bool <- not-equal top-of-screen, old-top +3174 ¦ # don't bother re-rendering if nothing changed. todo: test this +3175 ¦ return movement?/go-render +3176 } +3177 ] +3178 +3179 def page-up editor:&:editor, screen-height:num -> editor:&:editor [ +3180 local-scope +3181 load-ingredients +3182 max:num <- subtract screen-height, 1/menu-bar, 1/overlapping-line +3183 count:num <- copy 0 +3184 top-of-screen:&:duplex-list:char <- get *editor, top-of-screen:offset +3185 { +3186 ¦ done?:bool <- greater-or-equal count, max +3187 ¦ break-if done? +3188 ¦ prev:&:duplex-list:char <- before-previous-line top-of-screen, editor +3189 ¦ break-unless prev +3190 ¦ top-of-screen <- copy prev +3191 ¦ *editor <- put *editor, top-of-screen:offset, top-of-screen +3192 ¦ count <- add count, 1 +3193 ¦ loop +3194 } +3195 ] +3196 +3197 scenario editor-can-scroll-up-multiple-pages [ +3198 local-scope +3199 # screen has 1 line for menu + 3 lines +3200 assume-screen 10/width, 4/height +3201 # initialize editor with 8 lines +3202 s:text <- new [a +3203 b +3204 c +3205 d +3206 e +3207 f +3208 g +3209 h] +3210 e:&:editor <- new-editor s, 0/left, 10/right +3211 editor-render screen, e +3212 screen-should-contain [ +3213 ¦ . . +3214 ¦ .a . +3215 ¦ .b . +3216 ¦ .c . +3217 ] +3218 # scroll down two pages +3219 assume-console [ +3220 ¦ press page-down +3221 ¦ press page-down +3222 ] +3223 run [ +3224 ¦ editor-event-loop screen, console, e 3225 ] -3226 # scroll back up past empty line -3227 assume-console [ -3228 ¦ press page-up -3229 ] -3230 run [ -3231 ¦ editor-event-loop screen, console, e +3226 # screen shows third page +3227 screen-should-contain [ +3228 ¦ . . +3229 ¦ .e . +3230 ¦ .f . +3231 ¦ .g . 3232 ] -3233 screen-should-contain [ -3234 ¦ . . -3235 ¦ .cxx . -3236 ¦ .dxx . -3237 ¦ .exx . -3238 ] -3239 ] -3240 -3241 scenario editor-can-scroll-up-past-empty-lines [ -3242 local-scope -3243 assume-screen 10/width, 4/height -3244 # text with empty line in second screen -3245 s:text <- new [axy -3246 bxy -3247 cxy -3248 -3249 dxy -3250 exy -3251 fxy -3252 gxy -3253 ] -3254 e:&:editor <- new-editor s, 0/left, 4/right -3255 editor-render screen, e -3256 screen-should-contain [ -3257 ¦ . . -3258 ¦ .axy . -3259 ¦ .bxy . -3260 ¦ .cxy . -3261 ] -3262 assume-console [ -3263 ¦ press page-down -3264 ] -3265 run [ -3266 ¦ editor-event-loop screen, console, e -3267 ] -3268 screen-should-contain [ -3269 ¦ . . -3270 ¦ .cxy . -3271 ¦ . . -3272 ¦ .dxy . -3273 ] -3274 assume-console [ -3275 ¦ press page-down -3276 ] -3277 run [ -3278 ¦ editor-event-loop screen, console, e -3279 ] -3280 screen-should-contain [ -3281 ¦ . . -3282 ¦ .dxy . -3283 ¦ .exy . -3284 ¦ .fxy . -3285 ] -3286 # scroll back up past empty line -3287 assume-console [ -3288 ¦ press page-up +3233 # scroll up +3234 assume-console [ +3235 ¦ press page-up +3236 ] +3237 run [ +3238 ¦ editor-event-loop screen, console, e +3239 ] +3240 # screen shows second page +3241 screen-should-contain [ +3242 ¦ . . +3243 ¦ .c . +3244 ¦ .d . +3245 ¦ .e . +3246 ] +3247 # scroll up again +3248 assume-console [ +3249 ¦ press page-up +3250 ] +3251 run [ +3252 ¦ editor-event-loop screen, console, e +3253 ] +3254 # screen shows original page again +3255 screen-should-contain [ +3256 ¦ . . +3257 ¦ .a . +3258 ¦ .b . +3259 ¦ .c . +3260 ] +3261 ] +3262 +3263 scenario editor-can-scroll-up-wrapped-lines [ +3264 local-scope +3265 # screen has 1 line for menu + 5 lines for text +3266 assume-screen 10/width, 6/height +3267 # editor contains a long line in the first page +3268 s:text <- new [a +3269 b +3270 cdefgh +3271 i +3272 j +3273 k +3274 l +3275 m +3276 n +3277 o] +3278 # editor screen triggers wrap of last line +3279 e:&:editor <- new-editor s, 0/left, 4/right +3280 editor-render screen, e +3281 # some part of last line is not displayed +3282 screen-should-contain [ +3283 ¦ . . +3284 ¦ .a . +3285 ¦ .b . +3286 ¦ .cde↩ . +3287 ¦ .fgh . +3288 ¦ .i . 3289 ] -3290 run [ -3291 ¦ editor-event-loop screen, console, e -3292 ] -3293 screen-should-contain [ -3294 ¦ . . -3295 ¦ .cxy . -3296 ¦ . . -3297 ¦ .dxy . +3290 # scroll down a page and a line +3291 assume-console [ +3292 ¦ press page-down +3293 ¦ left-click 5, 0 +3294 ¦ press down-arrow +3295 ] +3296 run [ +3297 ¦ editor-event-loop screen, console, e 3298 ] -3299 ] +3299 # screen shows entire wrapped line +3300 screen-should-contain [ +3301 ¦ . . +3302 ¦ .j . +3303 ¦ .k . +3304 ¦ .l . +3305 ¦ .m . +3306 ¦ .n . +3307 ] +3308 # now scroll up one page +3309 assume-console [ +3310 ¦ press page-up +3311 ] +3312 run [ +3313 ¦ editor-event-loop screen, console, e +3314 ] +3315 # screen resets +3316 screen-should-contain [ +3317 ¦ . . +3318 ¦ .b . +3319 ¦ .cde↩ . +3320 ¦ .fgh . +3321 ¦ .i . +3322 ¦ .j . +3323 ] +3324 ] +3325 +3326 scenario editor-can-scroll-up-wrapped-lines-2 [ +3327 local-scope +3328 # screen has 1 line for menu + 3 lines for text +3329 assume-screen 10/width, 4/height +3330 # editor contains a very long line that occupies last two lines of screen +3331 # and still has something left over +3332 s:text <- new [a +3333 bcdefgh] +3334 e:&:editor <- new-editor s, 0/left, 4/right +3335 editor-render screen, e +3336 # some part of last line is not displayed +3337 screen-should-contain [ +3338 ¦ . . +3339 ¦ .a . +3340 ¦ .bcd↩ . +3341 ¦ .efg↩ . +3342 ] +3343 # scroll down +3344 assume-console [ +3345 ¦ press page-down +3346 ] +3347 run [ +3348 ¦ editor-event-loop screen, console, e +3349 ] +3350 # screen shows entire wrapped line +3351 screen-should-contain [ +3352 ¦ . . +3353 ¦ .bcd↩ . +3354 ¦ .efg↩ . +3355 ¦ .h . +3356 ] +3357 # scroll back up +3358 assume-console [ +3359 ¦ press page-up +3360 ] +3361 run [ +3362 ¦ editor-event-loop screen, console, e +3363 ] +3364 # screen resets +3365 screen-should-contain [ +3366 ¦ . . +3367 ¦ .a . +3368 ¦ .bcd↩ . +3369 ¦ .efg↩ . +3370 ] +3371 ] +3372 +3373 scenario editor-can-scroll-up-past-nonempty-lines [ +3374 local-scope +3375 assume-screen 10/width, 4/height +3376 # text with empty line in second screen +3377 s:text <- new [axx +3378 bxx +3379 cxx +3380 dxx +3381 exx +3382 fxx +3383 gxx +3384 hxx +3385 ] +3386 e:&:editor <- new-editor s, 0/left, 4/right +3387 editor-render screen, e +3388 screen-should-contain [ +3389 ¦ . . +3390 ¦ .axx . +3391 ¦ .bxx . +3392 ¦ .cxx . +3393 ] +3394 assume-console [ +3395 ¦ press page-down +3396 ] +3397 run [ +3398 ¦ editor-event-loop screen, console, e +3399 ] +3400 screen-should-contain [ +3401 ¦ . . +3402 ¦ .cxx . +3403 ¦ .dxx . +3404 ¦ .exx . +3405 ] +3406 assume-console [ +3407 ¦ press page-down +3408 ] +3409 run [ +3410 ¦ editor-event-loop screen, console, e +3411 ] +3412 screen-should-contain [ +3413 ¦ . . +3414 ¦ .exx . +3415 ¦ .fxx . +3416 ¦ .gxx . +3417 ] +3418 # scroll back up past empty line +3419 assume-console [ +3420 ¦ press page-up +3421 ] +3422 run [ +3423 ¦ editor-event-loop screen, console, e +3424 ] +3425 screen-should-contain [ +3426 ¦ . . +3427 ¦ .cxx . +3428 ¦ .dxx . +3429 ¦ .exx . +3430 ] +3431 ] +3432 +3433 scenario editor-can-scroll-up-past-empty-lines [ +3434 local-scope +3435 assume-screen 10/width, 4/height +3436 # text with empty line in second screen +3437 s:text <- new [axy +3438 bxy +3439 cxy +3440 +3441 dxy +3442 exy +3443 fxy +3444 gxy +3445 ] +3446 e:&:editor <- new-editor s, 0/left, 4/right +3447 editor-render screen, e +3448 screen-should-contain [ +3449 ¦ . . +3450 ¦ .axy . +3451 ¦ .bxy . +3452 ¦ .cxy . +3453 ] +3454 assume-console [ +3455 ¦ press page-down +3456 ] +3457 run [ +3458 ¦ editor-event-loop screen, console, e +3459 ] +3460 screen-should-contain [ +3461 ¦ . . +3462 ¦ .cxy . +3463 ¦ . . +3464 ¦ .dxy . +3465 ] +3466 assume-console [ +3467 ¦ press page-down +3468 ] +3469 run [ +3470 ¦ editor-event-loop screen, console, e +3471 ] +3472 screen-should-contain [ +3473 ¦ . . +3474 ¦ .dxy . +3475 ¦ .exy . +3476 ¦ .fxy . +3477 ] +3478 # scroll back up past empty line +3479 assume-console [ +3480 ¦ press page-up +3481 ] +3482 run [ +3483 ¦ editor-event-loop screen, console, e +3484 ] +3485 screen-should-contain [ +3486 ¦ . . +3487 ¦ .cxy . +3488 ¦ . . +3489 ¦ .dxy . +3490 ] +3491 ] diff --git a/html/edit/005-sandbox.mu.html b/html/edit/005-sandbox.mu.html index d7a503e5..580cec66 100644 --- a/html/edit/005-sandbox.mu.html +++ b/html/edit/005-sandbox.mu.html @@ -75,7 +75,7 @@ if ('onhashchange' in window) { 12 open-console 13 clear-screen 0/screen # non-scrolling app 14 env:&:environment <- new-programming-environment 0/filesystem, 0/screen - 15 env <- restore-sandboxes env + 15 env <- restore-sandboxes env 16 render-all 0/screen, env, render 17 event-loop 0/screen, 0/console, env, 0/filesystem 18 ] @@ -212,7 +212,7 @@ if ('onhashchange' in window) { 149 <run-sandboxes-begin> 150 current-sandbox:&:editor <- get *env, current-sandbox:offset 151 { - 152 ¦ sandbox-contents:text <- editor-contents current-sandbox + 152 ¦ sandbox-contents:text <- editor-contents current-sandbox 153 ¦ break-unless sandbox-contents 154 ¦ # if contents exist, first save them 155 ¦ # run them and turn them into a new sandbox @@ -257,7 +257,7 @@ if ('onhashchange' in window) { 194 local-scope 195 load-ingredients 196 recipes:&:editor <- get *env, recipes:offset - 197 in:text <- editor-contents recipes + 197 in:text <- editor-contents recipes 198 resources <- dump resources, [lesson/recipes.mu], in 199 reload in 200 errors-found? <- copy 0/false @@ -344,7 +344,7 @@ if ('onhashchange' in window) { 281 ¦ row <- add row, 1 282 ¦ screen <- move-cursor screen, row, left 283 ¦ sandbox-data:text <- get *sandbox, data:offset - 284 ¦ row, screen <- render-code screen, sandbox-data, left, right, row + 284 ¦ row, screen <- render-code screen, sandbox-data, left, right, row 285 ¦ *sandbox <- put *sandbox, code-ending-row-on-screen:offset, row 286 ¦ # render sandbox warnings, screen or response, in that order 287 ¦ sandbox-response:text <- get *sandbox, response:offset @@ -353,12 +353,12 @@ if ('onhashchange' in window) { 290 ¦ ¦ sandbox-screen:&:screen <- get *sandbox, screen:offset 291 ¦ ¦ empty-screen?:bool <- fake-screen-is-empty? sandbox-screen 292 ¦ ¦ break-if empty-screen? - 293 ¦ ¦ row, screen <- render-screen screen, sandbox-screen, left, right, row + 293 ¦ ¦ row, screen <- render-screen screen, sandbox-screen, left, right, row 294 ¦ } 295 ¦ { 296 ¦ ¦ break-unless empty-screen? 297 ¦ ¦ <render-sandbox-response> - 298 ¦ ¦ row, screen <- render-text screen, sandbox-response, left, right, 245/grey, row + 298 ¦ ¦ row, screen <- render-text screen, sandbox-response, left, right, 245/grey, row 299 ¦ } 300 ¦ +render-sandbox-end 301 ¦ at-bottom?:bool <- greater-or-equal row, screen-height @@ -421,944 +421,880 @@ if ('onhashchange' in window) { 358 359 # print a text 's' to 'editor' in 'color' starting at 'row' 360 # clear rest of last line, move cursor to next line - 361 def render-text screen:&:screen, s:text, left:num, right:num, color:num, row:num -> row:num, screen:&:screen [ - 362 local-scope - 363 load-ingredients - 364 return-unless s - 365 column:num <- copy left - 366 screen <- move-cursor screen, row, column - 367 screen-height:num <- screen-height screen - 368 i:num <- copy 0 - 369 len:num <- length *s - 370 { - 371 ¦ +next-character - 372 ¦ done?:bool <- greater-or-equal i, len - 373 ¦ break-if done? - 374 ¦ done? <- greater-or-equal row, screen-height - 375 ¦ break-if done? - 376 ¦ c:char <- index *s, i - 377 ¦ { - 378 ¦ ¦ # newline? move to left rather than 0 - 379 ¦ ¦ newline?:bool <- equal c, 10/newline - 380 ¦ ¦ break-unless newline? - 381 ¦ ¦ # clear rest of line in this window - 382 ¦ ¦ { - 383 ¦ ¦ ¦ done?:bool <- greater-than column, right - 384 ¦ ¦ ¦ break-if done? - 385 ¦ ¦ ¦ space:char <- copy 32/space - 386 ¦ ¦ ¦ print screen, space - 387 ¦ ¦ ¦ column <- add column, 1 - 388 ¦ ¦ ¦ loop - 389 ¦ ¦ } - 390 ¦ ¦ row <- add row, 1 - 391 ¦ ¦ column <- copy left - 392 ¦ ¦ screen <- move-cursor screen, row, column - 393 ¦ ¦ i <- add i, 1 - 394 ¦ ¦ loop +next-character - 395 ¦ } - 396 ¦ { - 397 ¦ ¦ # at right? wrap. - 398 ¦ ¦ at-right?:bool <- equal column, right - 399 ¦ ¦ break-unless at-right? - 400 ¦ ¦ # print wrap icon - 401 ¦ ¦ wrap-icon:char <- copy 8617/loop-back-to-left - 402 ¦ ¦ print screen, wrap-icon, 245/grey - 403 ¦ ¦ column <- copy left - 404 ¦ ¦ row <- add row, 1 - 405 ¦ ¦ screen <- move-cursor screen, row, column - 406 ¦ ¦ # don't increment i - 407 ¦ ¦ loop +next-character - 408 ¦ } - 409 ¦ i <- add i, 1 - 410 ¦ print screen, c, color - 411 ¦ column <- add column, 1 - 412 ¦ loop - 413 } - 414 was-at-left?:bool <- equal column, left - 415 clear-line-until screen, right - 416 { - 417 ¦ break-if was-at-left? - 418 ¦ row <- add row, 1 - 419 } - 420 move-cursor screen, row, left - 421 ] - 422 - 423 scenario read-text-wraps-barely-long-lines [ - 424 local-scope - 425 assume-screen 5/width, 5/height - 426 s:text <- new [abcde] - 427 run [ - 428 ¦ render-text screen, s, 0/left, 4/right, 7/white, 1/row - 429 ] - 430 screen-should-contain [ - 431 ¦ . . - 432 ¦ .abcd↩. - 433 ¦ .e . - 434 ¦ . . - 435 ] - 436 ] - 437 - 438 # like 'render-text', but with colorization for comments like in the editor - 439 def render-code screen:&:screen, s:text, left:num, right:num, row:num -> row:num, screen:&:screen [ - 440 local-scope - 441 load-ingredients - 442 return-unless s - 443 color:num <- copy 7/white - 444 column:num <- copy left - 445 screen <- move-cursor screen, row, column - 446 screen-height:num <- screen-height screen - 447 i:num <- copy 0 - 448 len:num <- length *s - 449 { - 450 ¦ +next-character - 451 ¦ done?:bool <- greater-or-equal i, len - 452 ¦ break-if done? - 453 ¦ done? <- greater-or-equal row, screen-height - 454 ¦ break-if done? - 455 ¦ c:char <- index *s, i - 456 ¦ <character-c-received> # only line different from 'render-text' - 457 ¦ { - 458 ¦ ¦ # newline? move to left rather than 0 - 459 ¦ ¦ newline?:bool <- equal c, 10/newline - 460 ¦ ¦ break-unless newline? - 461 ¦ ¦ # clear rest of line in this window - 462 ¦ ¦ { - 463 ¦ ¦ ¦ done?:bool <- greater-than column, right - 464 ¦ ¦ ¦ break-if done? - 465 ¦ ¦ ¦ space:char <- copy 32/space - 466 ¦ ¦ ¦ print screen, space - 467 ¦ ¦ ¦ column <- add column, 1 - 468 ¦ ¦ ¦ loop - 469 ¦ ¦ } - 470 ¦ ¦ row <- add row, 1 - 471 ¦ ¦ column <- copy left - 472 ¦ ¦ screen <- move-cursor screen, row, column - 473 ¦ ¦ i <- add i, 1 - 474 ¦ ¦ loop +next-character - 475 ¦ } - 476 ¦ { - 477 ¦ ¦ # at right? wrap. - 478 ¦ ¦ at-right?:bool <- equal column, right - 479 ¦ ¦ break-unless at-right? - 480 ¦ ¦ # print wrap icon - 481 ¦ ¦ wrap-icon:char <- copy 8617/loop-back-to-left - 482 ¦ ¦ print screen, wrap-icon, 245/grey - 483 ¦ ¦ column <- copy left - 484 ¦ ¦ row <- add row, 1 - 485 ¦ ¦ screen <- move-cursor screen, row, column - 486 ¦ ¦ # don't increment i - 487 ¦ ¦ loop +next-character - 488 ¦ } - 489 ¦ i <- add i, 1 - 490 ¦ print screen, c, color - 491 ¦ column <- add column, 1 - 492 ¦ loop - 493 } - 494 was-at-left?:bool <- equal column, left - 495 clear-line-until screen, right - 496 { - 497 ¦ break-if was-at-left? - 498 ¦ row <- add row, 1 - 499 } - 500 move-cursor screen, row, left - 501 ] - 502 - 503 # assumes programming environment has no sandboxes; restores them from previous session - 504 def restore-sandboxes env:&:environment, resources:&:resources -> env:&:environment [ - 505 local-scope - 506 load-ingredients - 507 # read all scenarios, pushing them to end of a list of scenarios - 508 idx:num <- copy 0 - 509 curr:&:sandbox <- copy 0 - 510 prev:&:sandbox <- copy 0 - 511 { - 512 ¦ filename:text <- append [lesson/], idx - 513 ¦ contents:text <- slurp resources, filename - 514 ¦ break-unless contents # stop at first error; assuming file didn't exist - 515 ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ # todo: handle empty sandbox - 516 ¦ # create new sandbox for file - 517 ¦ curr <- new sandbox:type - 518 ¦ *curr <- put *curr, data:offset, contents - 519 ¦ <end-restore-sandbox> - 520 ¦ { - 521 ¦ ¦ break-if idx - 522 ¦ ¦ *env <- put *env, sandbox:offset, curr - 523 ¦ } - 524 ¦ { - 525 ¦ ¦ break-unless idx - 526 ¦ ¦ *prev <- put *prev, next-sandbox:offset, curr - 527 ¦ } - 528 ¦ idx <- add idx, 1 - 529 ¦ prev <- copy curr - 530 ¦ loop - 531 } - 532 # update sandbox count - 533 *env <- put *env, number-of-sandboxes:offset, idx - 534 ] - 535 - 536 # print the fake sandbox screen to 'screen' with appropriate delimiters - 537 # leave cursor at start of next line - 538 def render-screen screen:&:screen, sandbox-screen:&:screen, left:num, right:num, row:num -> row:num, screen:&:screen [ - 539 local-scope - 540 load-ingredients - 541 return-unless sandbox-screen - 542 # print 'screen:' - 543 row <- render-text screen, [screen:], left, right, 245/grey, row - 544 screen <- move-cursor screen, row, left - 545 # start printing sandbox-screen - 546 column:num <- copy left - 547 s-width:num <- screen-width sandbox-screen - 548 s-height:num <- screen-height sandbox-screen - 549 buf:&:@:screen-cell <- get *sandbox-screen, data:offset - 550 stop-printing:num <- add left, s-width, 3 - 551 max-column:num <- min stop-printing, right - 552 i:num <- copy 0 - 553 len:num <- length *buf - 554 screen-height:num <- screen-height screen - 555 { - 556 ¦ done?:bool <- greater-or-equal i, len - 557 ¦ break-if done? - 558 ¦ done? <- greater-or-equal row, screen-height - 559 ¦ break-if done? - 560 ¦ column <- copy left - 561 ¦ screen <- move-cursor screen, row, column - 562 ¦ # initial leader for each row: two spaces and a '.' - 563 ¦ space:char <- copy 32/space - 564 ¦ print screen, space, 245/grey - 565 ¦ print screen, space, 245/grey - 566 ¦ full-stop:char <- copy 46/period - 567 ¦ print screen, full-stop, 245/grey - 568 ¦ column <- add left, 3 - 569 ¦ { - 570 ¦ ¦ # print row - 571 ¦ ¦ row-done?:bool <- greater-or-equal column, max-column - 572 ¦ ¦ break-if row-done? - 573 ¦ ¦ curr:screen-cell <- index *buf, i - 574 ¦ ¦ c:char <- get curr, contents:offset - 575 ¦ ¦ color:num <- get curr, color:offset - 576 ¦ ¦ { - 577 ¦ ¦ ¦ # damp whites down to grey - 578 ¦ ¦ ¦ white?:bool <- equal color, 7/white - 579 ¦ ¦ ¦ break-unless white? - 580 ¦ ¦ ¦ color <- copy 245/grey - 581 ¦ ¦ } - 582 ¦ ¦ print screen, c, color - 583 ¦ ¦ column <- add column, 1 - 584 ¦ ¦ i <- add i, 1 - 585 ¦ ¦ loop - 586 ¦ } - 587 ¦ # print final '.' - 588 ¦ print screen, full-stop, 245/grey - 589 ¦ column <- add column, 1 - 590 ¦ { - 591 ¦ ¦ # clear rest of current line - 592 ¦ ¦ line-done?:bool <- greater-than column, right - 593 ¦ ¦ break-if line-done? - 594 ¦ ¦ print screen, space - 595 ¦ ¦ column <- add column, 1 - 596 ¦ ¦ loop - 597 ¦ } - 598 ¦ row <- add row, 1 - 599 ¦ loop - 600 } - 601 ] - 602 - 603 scenario run-updates-results [ - 604 local-scope - 605 trace-until 100/app # trace too long - 606 assume-screen 100/width, 12/height - 607 # define a recipe (no indent for the 'add' line below so column numbers are more obvious) - 608 assume-resources [ - 609 ¦ [lesson/recipes.mu] <- [ - 610 ¦ ¦ || - 611 ¦ ¦ |recipe foo [| - 612 ¦ ¦ | local-scope| - 613 ¦ ¦ | z:num <- add 2, 2| - 614 ¦ ¦ | reply z| - 615 ¦ ¦ |]| - 616 ¦ ] - 617 ] - 618 # sandbox editor contains an instruction without storing outputs - 619 env:&:environment <- new-programming-environment resources, screen, [foo] # contents of sandbox editor - 620 # run the code in the editors - 621 assume-console [ - 622 ¦ press F4 - 623 ] - 624 event-loop screen, console, env, resources - 625 screen-should-contain [ - 626 ¦ . run (F4) . - 627 ¦ . ╎ . - 628 ¦ .recipe foo [ ╎─────────────────────────────────────────────────. - 629 ¦ . local-scope ╎0 edit copy delete . - 630 ¦ . z:num <- add 2, 2 ╎foo . - 631 ¦ . reply z ╎4 . - 632 ¦ .] ╎─────────────────────────────────────────────────. - 633 ¦ . ╎ . - 634 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . - 635 ¦ . ╎ . - 636 ] - 637 # make a change (incrementing one of the args to 'add'), then rerun - 638 assume-console [ - 639 ¦ left-click 4, 28 # one past the value of the second arg - 640 ¦ press backspace - 641 ¦ type [3] - 642 ¦ press F4 - 643 ] - 644 run [ - 645 ¦ event-loop screen, console, env, resources - 646 ] - 647 # check that screen updates the result on the right - 648 screen-should-contain [ - 649 ¦ . run (F4) . - 650 ¦ . ╎ . - 651 ¦ .recipe foo [ ╎─────────────────────────────────────────────────. - 652 ¦ . local-scope ╎0 edit copy delete . - 653 ¦ . z:num <- add 2, 3 ╎foo . - 654 ¦ . reply z ╎5 . - 655 ¦ .] ╎─────────────────────────────────────────────────. - 656 ¦ . ╎ . - 657 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . - 658 ¦ . ╎ . - 659 ] - 660 ] - 661 - 662 scenario run-instruction-manages-screen-per-sandbox [ - 663 local-scope - 664 trace-until 100/app # trace too long - 665 assume-screen 100/width, 20/height - 666 # empty recipes - 667 assume-resources [ - 668 ] - 669 # sandbox editor contains an instruction - 670 env:&:environment <- new-programming-environment resources, screen, [print screen, 4] # contents of sandbox editor - 671 # run the code in the editor - 672 assume-console [ - 673 ¦ press F4 - 674 ] - 675 run [ - 676 ¦ event-loop screen, console, env, resources - 677 ] - 678 # check that it prints a little toy screen - 679 screen-should-contain [ - 680 ¦ . run (F4) . - 681 ¦ . ╎ . - 682 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. - 683 ¦ . ╎0 edit copy delete . - 684 ¦ . ╎print screen, 4 . - 685 ¦ . ╎screen: . - 686 ¦ . ╎ .4 . . - 687 ¦ . ╎ . . . - 688 ¦ . ╎ . . . - 689 ¦ . ╎ . . . - 690 ¦ . ╎ . . . - 691 ¦ . ╎─────────────────────────────────────────────────. - 692 ¦ . ╎ . - 693 ] - 694 ] - 695 - 696 def editor-contents editor:&:editor -> result:text [ - 697 local-scope - 698 load-ingredients - 699 buf:&:buffer:char <- new-buffer 80 - 700 curr:&:duplex-list:char <- get *editor, data:offset - 701 # skip § sentinel - 702 assert curr, [editor without data is illegal; must have at least a sentinel] - 703 curr <- next curr - 704 return-unless curr, 0 - 705 { - 706 ¦ break-unless curr - 707 ¦ c:char <- get *curr, value:offset - 708 ¦ buf <- append buf, c - 709 ¦ curr <- next curr - 710 ¦ loop - 711 } - 712 result <- buffer-to-array buf - 713 ] - 714 - 715 scenario editor-provides-edited-contents [ - 716 local-scope - 717 assume-screen 10/width, 5/height - 718 e:&:editor <- new-editor [abc], 0/left, 10/right - 719 assume-console [ - 720 ¦ left-click 1, 2 - 721 ¦ type [def] - 722 ] - 723 run [ - 724 ¦ editor-event-loop screen, console, e - 725 ¦ s:text <- editor-contents e - 726 ¦ 1:@:char/raw <- copy *s - 727 ] - 728 memory-should-contain [ - 729 ¦ 1:array:character <- [abdefc] - 730 ] - 731 ] - 732 - 733 # keep the bottom of recipes from scrolling off the screen - 734 - 735 scenario scrolling-down-past-bottom-of-recipe-editor [ - 736 local-scope - 737 trace-until 100/app - 738 assume-screen 100/width, 10/height - 739 assume-resources [ - 740 ] - 741 env:&:environment <- new-programming-environment resources, screen, [] - 742 render-all screen, env, render - 743 assume-console [ - 744 ¦ press enter - 745 ¦ press down-arrow - 746 ] - 747 event-loop screen, console, env, resources - 748 # no scroll - 749 screen-should-contain [ - 750 ¦ . run (F4) . - 751 ¦ . ╎ . - 752 ¦ . ╎─────────────────────────────────────────────────. - 753 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . - 754 ¦ . ╎ . - 755 ] - 756 ] - 757 - 758 scenario cursor-down-in-recipe-editor [ - 759 local-scope - 760 trace-until 100/app - 761 assume-screen 100/width, 10/height - 762 assume-resources [ - 763 ] - 764 env:&:environment <- new-programming-environment resources, screen, [] - 765 render-all screen, env, render - 766 assume-console [ - 767 ¦ press enter - 768 ¦ press up-arrow - 769 ¦ press down-arrow # while cursor isn't at bottom - 770 ] - 771 event-loop screen, console, env, resources - 772 cursor:char <- copy 9251/␣ - 773 print screen, cursor - 774 # cursor moves back to bottom - 775 screen-should-contain [ - 776 ¦ . run (F4) . - 777 ¦ . ╎ . - 778 ¦ .␣ ╎─────────────────────────────────────────────────. - 779 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . - 780 ¦ . ╎ . - 781 ] - 782 ] - 783 - 784 # we'll not use the recipe-editor's 'bottom' element directly, because later - 785 # layers will add other stuff to the left side below the editor (error messages) - 786 - 787 container environment [ - 788 recipe-bottom:num - 789 ] - 790 - 791 after <render-recipe-components-end> [ - 792 *env <- put *env, recipe-bottom:offset, row - 793 ] - 794 - 795 after <global-keypress> [ - 796 { - 797 ¦ break-if sandbox-in-focus? - 798 ¦ down-arrow?:bool <- equal k, 65516/down-arrow - 799 ¦ break-unless down-arrow? - 800 ¦ recipe-editor:&:editor <- get *env, recipes:offset - 801 ¦ recipe-cursor-row:num <- get *recipe-editor, cursor-row:offset - 802 ¦ recipe-editor-bottom:num <- get *recipe-editor, bottom:offset - 803 ¦ at-bottom-of-editor?:bool <- greater-or-equal recipe-cursor-row, recipe-editor-bottom - 804 ¦ break-unless at-bottom-of-editor? - 805 ¦ more-to-scroll?:bool <- more-to-scroll? env, screen - 806 ¦ break-if more-to-scroll? - 807 ¦ loop +next-event - 808 } - 809 { - 810 ¦ break-if sandbox-in-focus? - 811 ¦ page-down?:bool <- equal k, 65518/page-down - 812 ¦ break-unless page-down? - 813 ¦ more-to-scroll?:bool <- more-to-scroll? env, screen - 814 ¦ break-if more-to-scroll? - 815 ¦ loop +next-event - 816 } - 817 ] - 818 - 819 after <global-type> [ - 820 { - 821 ¦ break-if sandbox-in-focus? - 822 ¦ page-down?:bool <- equal k, 6/ctrl-f - 823 ¦ break-unless page-down? - 824 ¦ more-to-scroll?:bool <- more-to-scroll? env, screen - 825 ¦ break-if more-to-scroll? - 826 ¦ loop +next-event - 827 } - 828 ] - 829 - 830 def more-to-scroll? env:&:environment, screen:&:screen -> result:bool [ - 831 local-scope - 832 load-ingredients - 833 recipe-bottom:num <- get *env, recipe-bottom:offset - 834 height:num <- screen-height screen - 835 result <- greater-or-equal recipe-bottom, height - 836 ] - 837 - 838 scenario scrolling-down-past-bottom-of-recipe-editor-2 [ - 839 local-scope - 840 trace-until 100/app - 841 assume-screen 100/width, 10/height - 842 assume-resources [ - 843 ] - 844 env:&:environment <- new-programming-environment resources, screen, [] - 845 render-all screen, env, render - 846 assume-console [ - 847 ¦ # add a line - 848 ¦ press enter - 849 ¦ # cursor back to top line - 850 ¦ press up-arrow - 851 ¦ # try to scroll - 852 ¦ press page-down # or ctrl-f + 361 # like 'render-code' but without syntax-based colorization + 362 def render-text screen:&:screen, s:text, left:num, right:num, color:num, row:num -> row:num, screen:&:screen [ + 363 local-scope + 364 load-ingredients + 365 return-unless s + 366 column:num <- copy left + 367 screen <- move-cursor screen, row, column + 368 screen-height:num <- screen-height screen + 369 i:num <- copy 0 + 370 len:num <- length *s + 371 { + 372 ¦ +next-character + 373 ¦ done?:bool <- greater-or-equal i, len + 374 ¦ break-if done? + 375 ¦ done? <- greater-or-equal row, screen-height + 376 ¦ break-if done? + 377 ¦ c:char <- index *s, i + 378 ¦ { + 379 ¦ ¦ # newline? move to left rather than 0 + 380 ¦ ¦ newline?:bool <- equal c, 10/newline + 381 ¦ ¦ break-unless newline? + 382 ¦ ¦ # clear rest of line in this window + 383 ¦ ¦ { + 384 ¦ ¦ ¦ done?:bool <- greater-than column, right + 385 ¦ ¦ ¦ break-if done? + 386 ¦ ¦ ¦ space:char <- copy 32/space + 387 ¦ ¦ ¦ print screen, space + 388 ¦ ¦ ¦ column <- add column, 1 + 389 ¦ ¦ ¦ loop + 390 ¦ ¦ } + 391 ¦ ¦ row <- add row, 1 + 392 ¦ ¦ column <- copy left + 393 ¦ ¦ screen <- move-cursor screen, row, column + 394 ¦ ¦ i <- add i, 1 + 395 ¦ ¦ loop +next-character + 396 ¦ } + 397 ¦ { + 398 ¦ ¦ # at right? wrap. + 399 ¦ ¦ at-right?:bool <- equal column, right + 400 ¦ ¦ break-unless at-right? + 401 ¦ ¦ # print wrap icon + 402 ¦ ¦ wrap-icon:char <- copy 8617/loop-back-to-left + 403 ¦ ¦ print screen, wrap-icon, 245/grey + 404 ¦ ¦ column <- copy left + 405 ¦ ¦ row <- add row, 1 + 406 ¦ ¦ screen <- move-cursor screen, row, column + 407 ¦ ¦ # don't increment i + 408 ¦ ¦ loop +next-character + 409 ¦ } + 410 ¦ i <- add i, 1 + 411 ¦ print screen, c, color + 412 ¦ column <- add column, 1 + 413 ¦ loop + 414 } + 415 was-at-left?:bool <- equal column, left + 416 clear-line-until screen, right + 417 { + 418 ¦ break-if was-at-left? + 419 ¦ row <- add row, 1 + 420 } + 421 move-cursor screen, row, left + 422 ] + 423 + 424 scenario read-text-wraps-barely-long-lines [ + 425 local-scope + 426 assume-screen 5/width, 5/height + 427 s:text <- new [abcde] + 428 run [ + 429 ¦ render-text screen, s, 0/left, 4/right, 7/white, 1/row + 430 ] + 431 screen-should-contain [ + 432 ¦ . . + 433 ¦ .abcd↩. + 434 ¦ .e . + 435 ¦ . . + 436 ] + 437 ] + 438 + 439 # assumes programming environment has no sandboxes; restores them from previous session + 440 def restore-sandboxes env:&:environment, resources:&:resources -> env:&:environment [ + 441 local-scope + 442 load-ingredients + 443 # read all scenarios, pushing them to end of a list of scenarios + 444 idx:num <- copy 0 + 445 curr:&:sandbox <- copy 0 + 446 prev:&:sandbox <- copy 0 + 447 { + 448 ¦ filename:text <- append [lesson/], idx + 449 ¦ contents:text <- slurp resources, filename + 450 ¦ break-unless contents # stop at first error; assuming file didn't exist + 451 ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ # todo: handle empty sandbox + 452 ¦ # create new sandbox for file + 453 ¦ curr <- new sandbox:type + 454 ¦ *curr <- put *curr, data:offset, contents + 455 ¦ <end-restore-sandbox> + 456 ¦ { + 457 ¦ ¦ break-if idx + 458 ¦ ¦ *env <- put *env, sandbox:offset, curr + 459 ¦ } + 460 ¦ { + 461 ¦ ¦ break-unless idx + 462 ¦ ¦ *prev <- put *prev, next-sandbox:offset, curr + 463 ¦ } + 464 ¦ idx <- add idx, 1 + 465 ¦ prev <- copy curr + 466 ¦ loop + 467 } + 468 # update sandbox count + 469 *env <- put *env, number-of-sandboxes:offset, idx + 470 ] + 471 + 472 # print the fake sandbox screen to 'screen' with appropriate delimiters + 473 # leave cursor at start of next line + 474 def render-screen screen:&:screen, sandbox-screen:&:screen, left:num, right:num, row:num -> row:num, screen:&:screen [ + 475 local-scope + 476 load-ingredients + 477 return-unless sandbox-screen + 478 # print 'screen:' + 479 row <- render-text screen, [screen:], left, right, 245/grey, row + 480 screen <- move-cursor screen, row, left + 481 # start printing sandbox-screen + 482 column:num <- copy left + 483 s-width:num <- screen-width sandbox-screen + 484 s-height:num <- screen-height sandbox-screen + 485 buf:&:@:screen-cell <- get *sandbox-screen, data:offset + 486 stop-printing:num <- add left, s-width, 3 + 487 max-column:num <- min stop-printing, right + 488 i:num <- copy 0 + 489 len:num <- length *buf + 490 screen-height:num <- screen-height screen + 491 { + 492 ¦ done?:bool <- greater-or-equal i, len + 493 ¦ break-if done? + 494 ¦ done? <- greater-or-equal row, screen-height + 495 ¦ break-if done? + 496 ¦ column <- copy left + 497 ¦ screen <- move-cursor screen, row, column + 498 ¦ # initial leader for each row: two spaces and a '.' + 499 ¦ space:char <- copy 32/space + 500 ¦ print screen, space, 245/grey + 501 ¦ print screen, space, 245/grey + 502 ¦ full-stop:char <- copy 46/period + 503 ¦ print screen, full-stop, 245/grey + 504 ¦ column <- add left, 3 + 505 ¦ { + 506 ¦ ¦ # print row + 507 ¦ ¦ row-done?:bool <- greater-or-equal column, max-column + 508 ¦ ¦ break-if row-done? + 509 ¦ ¦ curr:screen-cell <- index *buf, i + 510 ¦ ¦ c:char <- get curr, contents:offset + 511 ¦ ¦ color:num <- get curr, color:offset + 512 ¦ ¦ { + 513 ¦ ¦ ¦ # damp whites down to grey + 514 ¦ ¦ ¦ white?:bool <- equal color, 7/white + 515 ¦ ¦ ¦ break-unless white? + 516 ¦ ¦ ¦ color <- copy 245/grey + 517 ¦ ¦ } + 518 ¦ ¦ print screen, c, color + 519 ¦ ¦ column <- add column, 1 + 520 ¦ ¦ i <- add i, 1 + 521 ¦ ¦ loop + 522 ¦ } + 523 ¦ # print final '.' + 524 ¦ print screen, full-stop, 245/grey + 525 ¦ column <- add column, 1 + 526 ¦ { + 527 ¦ ¦ # clear rest of current line + 528 ¦ ¦ line-done?:bool <- greater-than column, right + 529 ¦ ¦ break-if line-done? + 530 ¦ ¦ print screen, space + 531 ¦ ¦ column <- add column, 1 + 532 ¦ ¦ loop + 533 ¦ } + 534 ¦ row <- add row, 1 + 535 ¦ loop + 536 } + 537 ] + 538 + 539 scenario run-updates-results [ + 540 local-scope + 541 trace-until 100/app # trace too long + 542 assume-screen 100/width, 12/height + 543 # define a recipe (no indent for the 'add' line below so column numbers are more obvious) + 544 assume-resources [ + 545 ¦ [lesson/recipes.mu] <- [ + 546 ¦ ¦ || + 547 ¦ ¦ |recipe foo [| + 548 ¦ ¦ | local-scope| + 549 ¦ ¦ | z:num <- add 2, 2| + 550 ¦ ¦ | reply z| + 551 ¦ ¦ |]| + 552 ¦ ] + 553 ] + 554 # sandbox editor contains an instruction without storing outputs + 555 env:&:environment <- new-programming-environment resources, screen, [foo] # contents of sandbox editor + 556 # run the code in the editors + 557 assume-console [ + 558 ¦ press F4 + 559 ] + 560 event-loop screen, console, env, resources + 561 screen-should-contain [ + 562 ¦ . run (F4) . + 563 ¦ . ╎ . + 564 ¦ .recipe foo [ ╎─────────────────────────────────────────────────. + 565 ¦ . local-scope ╎0 edit copy delete . + 566 ¦ . z:num <- add 2, 2 ╎foo . + 567 ¦ . reply z ╎4 . + 568 ¦ .] ╎─────────────────────────────────────────────────. + 569 ¦ . ╎ . + 570 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . + 571 ¦ . ╎ . + 572 ] + 573 # make a change (incrementing one of the args to 'add'), then rerun + 574 assume-console [ + 575 ¦ left-click 4, 28 # one past the value of the second arg + 576 ¦ press backspace + 577 ¦ type [3] + 578 ¦ press F4 + 579 ] + 580 run [ + 581 ¦ event-loop screen, console, env, resources + 582 ] + 583 # check that screen updates the result on the right + 584 screen-should-contain [ + 585 ¦ . run (F4) . + 586 ¦ . ╎ . + 587 ¦ .recipe foo [ ╎─────────────────────────────────────────────────. + 588 ¦ . local-scope ╎0 edit copy delete . + 589 ¦ . z:num <- add 2, 3 ╎foo . + 590 ¦ . reply z ╎5 . + 591 ¦ .] ╎─────────────────────────────────────────────────. + 592 ¦ . ╎ . + 593 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . + 594 ¦ . ╎ . + 595 ] + 596 ] + 597 + 598 scenario run-instruction-manages-screen-per-sandbox [ + 599 local-scope + 600 trace-until 100/app # trace too long + 601 assume-screen 100/width, 20/height + 602 # empty recipes + 603 assume-resources [ + 604 ] + 605 # sandbox editor contains an instruction + 606 env:&:environment <- new-programming-environment resources, screen, [print screen, 4] # contents of sandbox editor + 607 # run the code in the editor + 608 assume-console [ + 609 ¦ press F4 + 610 ] + 611 run [ + 612 ¦ event-loop screen, console, env, resources + 613 ] + 614 # check that it prints a little toy screen + 615 screen-should-contain [ + 616 ¦ . run (F4) . + 617 ¦ . ╎ . + 618 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + 619 ¦ . ╎0 edit copy delete . + 620 ¦ . ╎print screen, 4 . + 621 ¦ . ╎screen: . + 622 ¦ . ╎ .4 . . + 623 ¦ . ╎ . . . + 624 ¦ . ╎ . . . + 625 ¦ . ╎ . . . + 626 ¦ . ╎ . . . + 627 ¦ . ╎─────────────────────────────────────────────────. + 628 ¦ . ╎ . + 629 ] + 630 ] + 631 + 632 def editor-contents editor:&:editor -> result:text [ + 633 local-scope + 634 load-ingredients + 635 buf:&:buffer:char <- new-buffer 80 + 636 curr:&:duplex-list:char <- get *editor, data:offset + 637 # skip § sentinel + 638 assert curr, [editor without data is illegal; must have at least a sentinel] + 639 curr <- next curr + 640 return-unless curr, 0 + 641 { + 642 ¦ break-unless curr + 643 ¦ c:char <- get *curr, value:offset + 644 ¦ buf <- append buf, c + 645 ¦ curr <- next curr + 646 ¦ loop + 647 } + 648 result <- buffer-to-array buf + 649 ] + 650 + 651 scenario editor-provides-edited-contents [ + 652 local-scope + 653 assume-screen 10/width, 5/height + 654 e:&:editor <- new-editor [abc], 0/left, 10/right + 655 assume-console [ + 656 ¦ left-click 1, 2 + 657 ¦ type [def] + 658 ] + 659 run [ + 660 ¦ editor-event-loop screen, console, e + 661 ¦ s:text <- editor-contents e + 662 ¦ 1:@:char/raw <- copy *s + 663 ] + 664 memory-should-contain [ + 665 ¦ 1:array:character <- [abdefc] + 666 ] + 667 ] + 668 + 669 # keep the bottom of recipes from scrolling off the screen + 670 + 671 scenario scrolling-down-past-bottom-of-recipe-editor [ + 672 local-scope + 673 trace-until 100/app + 674 assume-screen 100/width, 10/height + 675 assume-resources [ + 676 ] + 677 env:&:environment <- new-programming-environment resources, screen, [] + 678 render-all screen, env, render + 679 assume-console [ + 680 ¦ press enter + 681 ¦ press down-arrow + 682 ] + 683 event-loop screen, console, env, resources + 684 # no scroll + 685 screen-should-contain [ + 686 ¦ . run (F4) . + 687 ¦ . ╎ . + 688 ¦ . ╎─────────────────────────────────────────────────. + 689 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . + 690 ¦ . ╎ . + 691 ] + 692 ] + 693 + 694 scenario cursor-down-in-recipe-editor [ + 695 local-scope + 696 trace-until 100/app + 697 assume-screen 100/width, 10/height + 698 assume-resources [ + 699 ] + 700 env:&:environment <- new-programming-environment resources, screen, [] + 701 render-all screen, env, render + 702 assume-console [ + 703 ¦ press enter + 704 ¦ press up-arrow + 705 ¦ press down-arrow # while cursor isn't at bottom + 706 ] + 707 event-loop screen, console, env, resources + 708 cursor:char <- copy 9251/␣ + 709 print screen, cursor + 710 # cursor moves back to bottom + 711 screen-should-contain [ + 712 ¦ . run (F4) . + 713 ¦ . ╎ . + 714 ¦ .␣ ╎─────────────────────────────────────────────────. + 715 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . + 716 ¦ . ╎ . + 717 ] + 718 ] + 719 + 720 # we'll not use the recipe-editor's 'bottom' element directly, because later + 721 # layers will add other stuff to the left side below the editor (error messages) + 722 + 723 container environment [ + 724 recipe-bottom:num + 725 ] + 726 + 727 after <render-recipe-components-end> [ + 728 *env <- put *env, recipe-bottom:offset, row + 729 ] + 730 + 731 after <global-keypress> [ + 732 { + 733 ¦ break-if sandbox-in-focus? + 734 ¦ down-arrow?:bool <- equal k, 65516/down-arrow + 735 ¦ break-unless down-arrow? + 736 ¦ recipe-editor:&:editor <- get *env, recipes:offset + 737 ¦ recipe-cursor-row:num <- get *recipe-editor, cursor-row:offset + 738 ¦ recipe-editor-bottom:num <- get *recipe-editor, bottom:offset + 739 ¦ at-bottom-of-editor?:bool <- greater-or-equal recipe-cursor-row, recipe-editor-bottom + 740 ¦ break-unless at-bottom-of-editor? + 741 ¦ more-to-scroll?:bool <- more-to-scroll? env, screen + 742 ¦ break-if more-to-scroll? + 743 ¦ loop +next-event + 744 } + 745 { + 746 ¦ break-if sandbox-in-focus? + 747 ¦ page-down?:bool <- equal k, 65518/page-down + 748 ¦ break-unless page-down? + 749 ¦ more-to-scroll?:bool <- more-to-scroll? env, screen + 750 ¦ break-if more-to-scroll? + 751 ¦ loop +next-event + 752 } + 753 ] + 754 + 755 after <global-type> [ + 756 { + 757 ¦ break-if sandbox-in-focus? + 758 ¦ page-down?:bool <- equal k, 6/ctrl-f + 759 ¦ break-unless page-down? + 760 ¦ more-to-scroll?:bool <- more-to-scroll? env, screen + 761 ¦ break-if more-to-scroll? + 762 ¦ loop +next-event + 763 } + 764 ] + 765 + 766 def more-to-scroll? env:&:environment, screen:&:screen -> result:bool [ + 767 local-scope + 768 load-ingredients + 769 recipe-bottom:num <- get *env, recipe-bottom:offset + 770 height:num <- screen-height screen + 771 result <- greater-or-equal recipe-bottom, height + 772 ] + 773 + 774 scenario scrolling-down-past-bottom-of-recipe-editor-2 [ + 775 local-scope + 776 trace-until 100/app + 777 assume-screen 100/width, 10/height + 778 assume-resources [ + 779 ] + 780 env:&:environment <- new-programming-environment resources, screen, [] + 781 render-all screen, env, render + 782 assume-console [ + 783 ¦ # add a line + 784 ¦ press enter + 785 ¦ # cursor back to top line + 786 ¦ press up-arrow + 787 ¦ # try to scroll + 788 ¦ press page-down # or ctrl-f + 789 ] + 790 event-loop screen, console, env, resources + 791 # no scroll, and cursor remains at top line + 792 screen-should-contain [ + 793 ¦ . run (F4) . + 794 ¦ . ╎ . + 795 ¦ . ╎─────────────────────────────────────────────────. + 796 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . + 797 ¦ . ╎ . + 798 ] + 799 ] + 800 + 801 scenario scrolling-down-past-bottom-of-recipe-editor-3 [ + 802 local-scope + 803 trace-until 100/app + 804 assume-screen 100/width, 10/height + 805 assume-resources [ + 806 ] + 807 env:&:environment <- new-programming-environment resources, screen, [ab + 808 cd] + 809 render-all screen, env, render + 810 assume-console [ + 811 ¦ # add a line + 812 ¦ press enter + 813 ¦ # switch to sandbox + 814 ¦ press ctrl-n + 815 ¦ # move cursor + 816 ¦ press down-arrow + 817 ] + 818 event-loop screen, console, env, resources + 819 cursor:char <- copy 9251/␣ + 820 print screen, cursor + 821 # no scroll on recipe side, cursor moves on sandbox side + 822 screen-should-contain [ + 823 ¦ . run (F4) . + 824 ¦ . ╎ab . + 825 ¦ . ╎␣d . + 826 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + 827 ¦ . ╎ . + 828 ] + 829 ] + 830 + 831 # scrolling through sandboxes + 832 + 833 scenario scrolling-down-past-bottom-of-sandbox-editor [ + 834 local-scope + 835 trace-until 100/app # trace too long + 836 assume-screen 100/width, 10/height + 837 # initialize + 838 assume-resources [ + 839 ] + 840 env:&:environment <- new-programming-environment resources, screen, [add 2, 2] + 841 render-all screen, env, render + 842 assume-console [ + 843 ¦ # create a sandbox + 844 ¦ press F4 + 845 ] + 846 event-loop screen, console, env, resources + 847 screen-should-contain [ + 848 ¦ . run (F4) . + 849 ¦ . ╎ . + 850 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + 851 ¦ . ╎0 edit copy delete . + 852 ¦ . ╎add 2, 2 . 853 ] - 854 event-loop screen, console, env, resources - 855 # no scroll, and cursor remains at top line - 856 screen-should-contain [ - 857 ¦ . run (F4) . - 858 ¦ . ╎ . - 859 ¦ . ╎─────────────────────────────────────────────────. - 860 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎ . - 861 ¦ . ╎ . - 862 ] - 863 ] - 864 - 865 scenario scrolling-down-past-bottom-of-recipe-editor-3 [ - 866 local-scope - 867 trace-until 100/app - 868 assume-screen 100/width, 10/height - 869 assume-resources [ - 870 ] - 871 env:&:environment <- new-programming-environment resources, screen, [ab - 872 cd] - 873 render-all screen, env, render + 854 # switch to sandbox window and hit 'page-down' + 855 assume-console [ + 856 ¦ press ctrl-n + 857 ¦ press page-down + 858 ] + 859 run [ + 860 ¦ event-loop screen, console, env, resources + 861 ¦ cursor:char <- copy 9251/␣ + 862 ¦ print screen, cursor + 863 ] + 864 # sandbox editor hidden; first sandbox displayed + 865 # cursor moves to first sandbox + 866 screen-should-contain [ + 867 ¦ . run (F4) . + 868 ¦ . ╎─────────────────────────────────────────────────. + 869 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎␣ edit copy delete . + 870 ¦ . ╎add 2, 2 . + 871 ¦ . ╎4 . + 872 ] + 873 # hit 'page-up' 874 assume-console [ - 875 ¦ # add a line - 876 ¦ press enter - 877 ¦ # switch to sandbox - 878 ¦ press ctrl-n - 879 ¦ # move cursor - 880 ¦ press down-arrow + 875 ¦ press page-up + 876 ] + 877 run [ + 878 ¦ event-loop screen, console, env, resources + 879 ¦ cursor:char <- copy 9251/␣ + 880 ¦ print screen, cursor 881 ] - 882 event-loop screen, console, env, resources - 883 cursor:char <- copy 9251/␣ - 884 print screen, cursor - 885 # no scroll on recipe side, cursor moves on sandbox side - 886 screen-should-contain [ - 887 ¦ . run (F4) . - 888 ¦ . ╎ab . - 889 ¦ . ╎␣d . - 890 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. - 891 ¦ . ╎ . - 892 ] - 893 ] - 894 - 895 # scrolling through sandboxes - 896 - 897 scenario scrolling-down-past-bottom-of-sandbox-editor [ - 898 local-scope - 899 trace-until 100/app # trace too long - 900 assume-screen 100/width, 10/height - 901 # initialize - 902 assume-resources [ - 903 ] - 904 env:&:environment <- new-programming-environment resources, screen, [add 2, 2] - 905 render-all screen, env, render - 906 assume-console [ - 907 ¦ # create a sandbox - 908 ¦ press F4 - 909 ] - 910 event-loop screen, console, env, resources - 911 screen-should-contain [ - 912 ¦ . run (F4) . - 913 ¦ . ╎ . - 914 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. - 915 ¦ . ╎0 edit copy delete . - 916 ¦ . ╎add 2, 2 . - 917 ] - 918 # switch to sandbox window and hit 'page-down' - 919 assume-console [ - 920 ¦ press ctrl-n - 921 ¦ press page-down - 922 ] - 923 run [ - 924 ¦ event-loop screen, console, env, resources - 925 ¦ cursor:char <- copy 9251/␣ - 926 ¦ print screen, cursor - 927 ] - 928 # sandbox editor hidden; first sandbox displayed - 929 # cursor moves to first sandbox - 930 screen-should-contain [ - 931 ¦ . run (F4) . - 932 ¦ . ╎─────────────────────────────────────────────────. - 933 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎␣ edit copy delete . - 934 ¦ . ╎add 2, 2 . - 935 ¦ . ╎4 . - 936 ] - 937 # hit 'page-up' - 938 assume-console [ - 939 ¦ press page-up - 940 ] - 941 run [ - 942 ¦ event-loop screen, console, env, resources - 943 ¦ cursor:char <- copy 9251/␣ - 944 ¦ print screen, cursor - 945 ] - 946 # sandbox editor displays again, cursor is in editor - 947 screen-should-contain [ - 948 ¦ . run (F4) . - 949 ¦ . ╎␣ . - 950 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. - 951 ¦ . ╎0 edit copy delete . - 952 ¦ . ╎add 2, 2 . - 953 ] - 954 ] - 955 - 956 # page-down on sandbox side updates render-from to scroll sandboxes - 957 after <global-keypress> [ - 958 { - 959 ¦ break-unless sandbox-in-focus? - 960 ¦ page-down?:bool <- equal k, 65518/page-down - 961 ¦ break-unless page-down? - 962 ¦ sandbox:&:sandbox <- get *env, sandbox:offset - 963 ¦ break-unless sandbox - 964 ¦ # slide down if possible - 965 ¦ { - 966 ¦ ¦ render-from:num <- get *env, render-from:offset - 967 ¦ ¦ number-of-sandboxes:num <- get *env, number-of-sandboxes:offset - 968 ¦ ¦ max:num <- subtract number-of-sandboxes, 1 - 969 ¦ ¦ at-end?:bool <- greater-or-equal render-from, max - 970 ¦ ¦ loop-if at-end?, +next-event # render nothing - 971 ¦ ¦ render-from <- add render-from, 1 - 972 ¦ ¦ *env <- put *env, render-from:offset, render-from - 973 ¦ } - 974 ¦ screen <- render-sandbox-side screen, env, render - 975 ¦ screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env - 976 ¦ loop +next-event - 977 } - 978 ] - 979 - 980 # update-cursor takes render-from into account - 981 after <update-cursor-special-cases> [ - 982 { - 983 ¦ break-unless sandbox-in-focus? - 984 ¦ render-from:num <- get *env, render-from:offset - 985 ¦ scrolling?:bool <- greater-or-equal render-from, 0 - 986 ¦ break-unless scrolling? - 987 ¦ cursor-column:num <- get *current-sandbox, left:offset - 988 ¦ screen <- move-cursor screen, 2/row, cursor-column # highlighted sandbox will always start at row 2 - 989 ¦ return - 990 } - 991 ] - 992 - 993 # 'page-up' on sandbox side is like 'page-down': updates render-from when necessary - 994 after <global-keypress> [ - 995 { - 996 ¦ break-unless sandbox-in-focus? - 997 ¦ page-up?:bool <- equal k, 65519/page-up - 998 ¦ break-unless page-up? - 999 ¦ render-from:num <- get *env, render-from:offset -1000 ¦ at-beginning?:bool <- equal render-from, -1 -1001 ¦ break-if at-beginning? -1002 ¦ render-from <- subtract render-from, 1 -1003 ¦ *env <- put *env, render-from:offset, render-from -1004 ¦ screen <- render-sandbox-side screen, env, render -1005 ¦ screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env -1006 ¦ loop +next-event -1007 } -1008 ] -1009 -1010 # sandbox belonging to 'env' whose next-sandbox is 'in' -1011 # return 0 if there's no such sandbox, either because 'in' doesn't exist in 'env', or because it's the first sandbox -1012 def previous-sandbox env:&:environment, in:&:sandbox -> out:&:sandbox [ -1013 local-scope -1014 load-ingredients -1015 curr:&:sandbox <- get *env, sandbox:offset -1016 return-unless curr, 0/nil -1017 next:&:sandbox <- get *curr, next-sandbox:offset -1018 { -1019 ¦ return-unless next, 0/nil -1020 ¦ found?:bool <- equal next, in -1021 ¦ break-if found? -1022 ¦ curr <- copy next -1023 ¦ next <- get *curr, next-sandbox:offset -1024 ¦ loop -1025 } -1026 return curr -1027 ] -1028 -1029 scenario scrolling-down-past-bottom-on-recipe-side [ -1030 local-scope -1031 trace-until 100/app # trace too long -1032 assume-screen 100/width, 10/height -1033 # initialize sandbox side and create a sandbox -1034 assume-resources [ -1035 ¦ [lesson/recipes.mu] <- [ -1036 ¦ ¦ || # file containing just a newline -1037 ¦ ] -1038 ] -1039 # create a sandbox -1040 env:&:environment <- new-programming-environment resources, screen, [add 2, 2] -1041 render-all screen, env, render -1042 assume-console [ -1043 ¦ press F4 -1044 ] -1045 event-loop screen, console, env, resources -1046 # hit 'down' in recipe editor -1047 assume-console [ -1048 ¦ press page-down -1049 ] -1050 run [ -1051 ¦ event-loop screen, console, env, resources -1052 ¦ cursor:char <- copy 9251/␣ -1053 ¦ print screen, cursor + 882 # sandbox editor displays again, cursor is in editor + 883 screen-should-contain [ + 884 ¦ . run (F4) . + 885 ¦ . ╎␣ . + 886 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. + 887 ¦ . ╎0 edit copy delete . + 888 ¦ . ╎add 2, 2 . + 889 ] + 890 ] + 891 + 892 # page-down on sandbox side updates render-from to scroll sandboxes + 893 after <global-keypress> [ + 894 { + 895 ¦ break-unless sandbox-in-focus? + 896 ¦ page-down?:bool <- equal k, 65518/page-down + 897 ¦ break-unless page-down? + 898 ¦ sandbox:&:sandbox <- get *env, sandbox:offset + 899 ¦ break-unless sandbox + 900 ¦ # slide down if possible + 901 ¦ { + 902 ¦ ¦ render-from:num <- get *env, render-from:offset + 903 ¦ ¦ number-of-sandboxes:num <- get *env, number-of-sandboxes:offset + 904 ¦ ¦ max:num <- subtract number-of-sandboxes, 1 + 905 ¦ ¦ at-end?:bool <- greater-or-equal render-from, max + 906 ¦ ¦ loop-if at-end?, +next-event # render nothing + 907 ¦ ¦ render-from <- add render-from, 1 + 908 ¦ ¦ *env <- put *env, render-from:offset, render-from + 909 ¦ } + 910 ¦ screen <- render-sandbox-side screen, env, render + 911 ¦ screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env + 912 ¦ loop +next-event + 913 } + 914 ] + 915 + 916 # update-cursor takes render-from into account + 917 after <update-cursor-special-cases> [ + 918 { + 919 ¦ break-unless sandbox-in-focus? + 920 ¦ render-from:num <- get *env, render-from:offset + 921 ¦ scrolling?:bool <- greater-or-equal render-from, 0 + 922 ¦ break-unless scrolling? + 923 ¦ cursor-column:num <- get *current-sandbox, left:offset + 924 ¦ screen <- move-cursor screen, 2/row, cursor-column # highlighted sandbox will always start at row 2 + 925 ¦ return + 926 } + 927 ] + 928 + 929 # 'page-up' on sandbox side is like 'page-down': updates render-from when necessary + 930 after <global-keypress> [ + 931 { + 932 ¦ break-unless sandbox-in-focus? + 933 ¦ page-up?:bool <- equal k, 65519/page-up + 934 ¦ break-unless page-up? + 935 ¦ render-from:num <- get *env, render-from:offset + 936 ¦ at-beginning?:bool <- equal render-from, -1 + 937 ¦ break-if at-beginning? + 938 ¦ render-from <- subtract render-from, 1 + 939 ¦ *env <- put *env, render-from:offset, render-from + 940 ¦ screen <- render-sandbox-side screen, env, render + 941 ¦ screen <- update-cursor screen, recipes, current-sandbox, sandbox-in-focus?, env + 942 ¦ loop +next-event + 943 } + 944 ] + 945 + 946 # sandbox belonging to 'env' whose next-sandbox is 'in' + 947 # return 0 if there's no such sandbox, either because 'in' doesn't exist in 'env', or because it's the first sandbox + 948 def previous-sandbox env:&:environment, in:&:sandbox -> out:&:sandbox [ + 949 local-scope + 950 load-ingredients + 951 curr:&:sandbox <- get *env, sandbox:offset + 952 return-unless curr, 0/nil + 953 next:&:sandbox <- get *curr, next-sandbox:offset + 954 { + 955 ¦ return-unless next, 0/nil + 956 ¦ found?:bool <- equal next, in + 957 ¦ break-if found? + 958 ¦ curr <- copy next + 959 ¦ next <- get *curr, next-sandbox:offset + 960 ¦ loop + 961 } + 962 return curr + 963 ] + 964 + 965 scenario scrolling-down-past-bottom-on-recipe-side [ + 966 local-scope + 967 trace-until 100/app # trace too long + 968 assume-screen 100/width, 10/height + 969 # initialize sandbox side and create a sandbox + 970 assume-resources [ + 971 ¦ [lesson/recipes.mu] <- [ + 972 ¦ ¦ || # file containing just a newline + 973 ¦ ] + 974 ] + 975 # create a sandbox + 976 env:&:environment <- new-programming-environment resources, screen, [add 2, 2] + 977 render-all screen, env, render + 978 assume-console [ + 979 ¦ press F4 + 980 ] + 981 event-loop screen, console, env, resources + 982 # hit 'down' in recipe editor + 983 assume-console [ + 984 ¦ press page-down + 985 ] + 986 run [ + 987 ¦ event-loop screen, console, env, resources + 988 ¦ cursor:char <- copy 9251/␣ + 989 ¦ print screen, cursor + 990 ] + 991 # cursor doesn't move when the end is already on-screen + 992 screen-should-contain [ + 993 ¦ . run (F4) . + 994 ¦ .␣ ╎ . + 995 ¦ . ╎─────────────────────────────────────────────────. + 996 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy delete . + 997 ¦ . ╎add 2, 2 . + 998 ] + 999 ] +1000 +1001 scenario scrolling-through-multiple-sandboxes [ +1002 local-scope +1003 trace-until 100/app # trace too long +1004 assume-screen 100/width, 10/height +1005 # initialize environment +1006 assume-resources [ +1007 ] +1008 env:&:environment <- new-programming-environment resources, screen, [] +1009 render-all screen, env, render +1010 # create 2 sandboxes +1011 assume-console [ +1012 ¦ press ctrl-n +1013 ¦ type [add 2, 2] +1014 ¦ press F4 +1015 ¦ type [add 1, 1] +1016 ¦ press F4 +1017 ] +1018 event-loop screen, console, env, resources +1019 cursor:char <- copy 9251/␣ +1020 print screen, cursor +1021 screen-should-contain [ +1022 ¦ . run (F4) . +1023 ¦ . ╎␣ . +1024 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. +1025 ¦ . ╎0 edit copy delete . +1026 ¦ . ╎add 1, 1 . +1027 ¦ . ╎2 . +1028 ¦ . ╎─────────────────────────────────────────────────. +1029 ¦ . ╎1 edit copy delete . +1030 ¦ . ╎add 2, 2 . +1031 ¦ . ╎4 . +1032 ] +1033 # hit 'page-down' +1034 assume-console [ +1035 ¦ press page-down +1036 ] +1037 run [ +1038 ¦ event-loop screen, console, env, resources +1039 ¦ cursor:char <- copy 9251/␣ +1040 ¦ print screen, cursor +1041 ] +1042 # sandbox editor hidden; first sandbox displayed +1043 # cursor moves to first sandbox +1044 screen-should-contain [ +1045 ¦ . run (F4) . +1046 ¦ . ╎─────────────────────────────────────────────────. +1047 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎␣ edit copy delete . +1048 ¦ . ╎add 1, 1 . +1049 ¦ . ╎2 . +1050 ¦ . ╎─────────────────────────────────────────────────. +1051 ¦ . ╎1 edit copy delete . +1052 ¦ . ╎add 2, 2 . +1053 ¦ . ╎4 . 1054 ] -1055 # cursor doesn't move when the end is already on-screen -1056 screen-should-contain [ -1057 ¦ . run (F4) . -1058 ¦ .␣ ╎ . -1059 ¦ . ╎─────────────────────────────────────────────────. -1060 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy delete . -1061 ¦ . ╎add 2, 2 . -1062 ] -1063 ] -1064 -1065 scenario scrolling-through-multiple-sandboxes [ -1066 local-scope -1067 trace-until 100/app # trace too long -1068 assume-screen 100/width, 10/height -1069 # initialize environment -1070 assume-resources [ +1055 # hit 'page-down' again +1056 assume-console [ +1057 ¦ press page-down +1058 ] +1059 run [ +1060 ¦ event-loop screen, console, env, resources +1061 ] +1062 # just second sandbox displayed +1063 screen-should-contain [ +1064 ¦ . run (F4) . +1065 ¦ . ╎─────────────────────────────────────────────────. +1066 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎1 edit copy delete . +1067 ¦ . ╎add 2, 2 . +1068 ¦ . ╎4 . +1069 ¦ . ╎─────────────────────────────────────────────────. +1070 ¦ . ╎ . 1071 ] -1072 env:&:environment <- new-programming-environment resources, screen, [] -1073 render-all screen, env, render -1074 # create 2 sandboxes -1075 assume-console [ -1076 ¦ press ctrl-n -1077 ¦ type [add 2, 2] -1078 ¦ press F4 -1079 ¦ type [add 1, 1] -1080 ¦ press F4 -1081 ] -1082 event-loop screen, console, env, resources -1083 cursor:char <- copy 9251/␣ -1084 print screen, cursor -1085 screen-should-contain [ -1086 ¦ . run (F4) . -1087 ¦ . ╎␣ . -1088 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. -1089 ¦ . ╎0 edit copy delete . -1090 ¦ . ╎add 1, 1 . -1091 ¦ . ╎2 . -1092 ¦ . ╎─────────────────────────────────────────────────. -1093 ¦ . ╎1 edit copy delete . -1094 ¦ . ╎add 2, 2 . -1095 ¦ . ╎4 . -1096 ] -1097 # hit 'page-down' -1098 assume-console [ -1099 ¦ press page-down -1100 ] -1101 run [ -1102 ¦ event-loop screen, console, env, resources -1103 ¦ cursor:char <- copy 9251/␣ -1104 ¦ print screen, cursor -1105 ] -1106 # sandbox editor hidden; first sandbox displayed -1107 # cursor moves to first sandbox -1108 screen-should-contain [ -1109 ¦ . run (F4) . -1110 ¦ . ╎─────────────────────────────────────────────────. -1111 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎␣ edit copy delete . -1112 ¦ . ╎add 1, 1 . -1113 ¦ . ╎2 . -1114 ¦ . ╎─────────────────────────────────────────────────. -1115 ¦ . ╎1 edit copy delete . -1116 ¦ . ╎add 2, 2 . -1117 ¦ . ╎4 . -1118 ] -1119 # hit 'page-down' again -1120 assume-console [ -1121 ¦ press page-down -1122 ] -1123 run [ -1124 ¦ event-loop screen, console, env, resources -1125 ] -1126 # just second sandbox displayed -1127 screen-should-contain [ -1128 ¦ . run (F4) . -1129 ¦ . ╎─────────────────────────────────────────────────. -1130 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎1 edit copy delete . -1131 ¦ . ╎add 2, 2 . -1132 ¦ . ╎4 . -1133 ¦ . ╎─────────────────────────────────────────────────. -1134 ¦ . ╎ . -1135 ] -1136 # hit 'page-down' again -1137 assume-console [ -1138 ¦ press page-down -1139 ] -1140 run [ -1141 ¦ event-loop screen, console, env, resources -1142 ] -1143 # no change -1144 screen-should-contain [ -1145 ¦ . run (F4) . -1146 ¦ . ╎─────────────────────────────────────────────────. -1147 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎1 edit copy delete . -1148 ¦ . ╎add 2, 2 . -1149 ¦ . ╎4 . -1150 ¦ . ╎─────────────────────────────────────────────────. -1151 ¦ . ╎ . -1152 ] -1153 # hit 'page-up' -1154 assume-console [ -1155 ¦ press page-up -1156 ] -1157 run [ -1158 ¦ event-loop screen, console, env, resources -1159 ] -1160 # back to displaying both sandboxes without editor -1161 screen-should-contain [ -1162 ¦ . run (F4) . -1163 ¦ . ╎─────────────────────────────────────────────────. -1164 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy delete . -1165 ¦ . ╎add 1, 1 . -1166 ¦ . ╎2 . -1167 ¦ . ╎─────────────────────────────────────────────────. -1168 ¦ . ╎1 edit copy delete . -1169 ¦ . ╎add 2, 2 . -1170 ¦ . ╎4 . -1171 ] -1172 # hit 'page-up' again -1173 assume-console [ -1174 ¦ press page-up -1175 ] -1176 run [ -1177 ¦ event-loop screen, console, env, resources -1178 ¦ cursor:char <- copy 9251/␣ -1179 ¦ print screen, cursor -1180 ] -1181 # back to displaying both sandboxes as well as editor -1182 screen-should-contain [ -1183 ¦ . run (F4) . -1184 ¦ . ╎␣ . -1185 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. -1186 ¦ . ╎0 edit copy delete . -1187 ¦ . ╎add 1, 1 . -1188 ¦ . ╎2 . -1189 ¦ . ╎─────────────────────────────────────────────────. -1190 ¦ . ╎1 edit copy delete . -1191 ¦ . ╎add 2, 2 . -1192 ¦ . ╎4 . -1193 ] -1194 # hit 'page-up' again -1195 assume-console [ -1196 ¦ press page-up +1072 # hit 'page-down' again +1073 assume-console [ +1074 ¦ press page-down +1075 ] +1076 run [ +1077 ¦ event-loop screen, console, env, resources +1078 ] +1079 # no change +1080 screen-should-contain [ +1081 ¦ . run (F4) . +1082 ¦ . ╎─────────────────────────────────────────────────. +1083 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎1 edit copy delete . +1084 ¦ . ╎add 2, 2 . +1085 ¦ . ╎4 . +1086 ¦ . ╎─────────────────────────────────────────────────. +1087 ¦ . ╎ . +1088 ] +1089 # hit 'page-up' +1090 assume-console [ +1091 ¦ press page-up +1092 ] +1093 run [ +1094 ¦ event-loop screen, console, env, resources +1095 ] +1096 # back to displaying both sandboxes without editor +1097 screen-should-contain [ +1098 ¦ . run (F4) . +1099 ¦ . ╎─────────────────────────────────────────────────. +1100 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy delete . +1101 ¦ . ╎add 1, 1 . +1102 ¦ . ╎2 . +1103 ¦ . ╎─────────────────────────────────────────────────. +1104 ¦ . ╎1 edit copy delete . +1105 ¦ . ╎add 2, 2 . +1106 ¦ . ╎4 . +1107 ] +1108 # hit 'page-up' again +1109 assume-console [ +1110 ¦ press page-up +1111 ] +1112 run [ +1113 ¦ event-loop screen, console, env, resources +1114 ¦ cursor:char <- copy 9251/␣ +1115 ¦ print screen, cursor +1116 ] +1117 # back to displaying both sandboxes as well as editor +1118 screen-should-contain [ +1119 ¦ . run (F4) . +1120 ¦ . ╎␣ . +1121 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. +1122 ¦ . ╎0 edit copy delete . +1123 ¦ . ╎add 1, 1 . +1124 ¦ . ╎2 . +1125 ¦ . ╎─────────────────────────────────────────────────. +1126 ¦ . ╎1 edit copy delete . +1127 ¦ . ╎add 2, 2 . +1128 ¦ . ╎4 . +1129 ] +1130 # hit 'page-up' again +1131 assume-console [ +1132 ¦ press page-up +1133 ] +1134 run [ +1135 ¦ event-loop screen, console, env, resources +1136 ¦ cursor:char <- copy 9251/␣ +1137 ¦ print screen, cursor +1138 ] +1139 # no change +1140 screen-should-contain [ +1141 ¦ . run (F4) . +1142 ¦ . ╎␣ . +1143 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. +1144 ¦ . ╎0 edit copy delete . +1145 ¦ . ╎add 1, 1 . +1146 ¦ . ╎2 . +1147 ¦ . ╎─────────────────────────────────────────────────. +1148 ¦ . ╎1 edit copy delete . +1149 ¦ . ╎add 2, 2 . +1150 ¦ . ╎4 . +1151 ] +1152 ] +1153 +1154 scenario scrolling-manages-sandbox-index-correctly [ +1155 local-scope +1156 trace-until 100/app # trace too long +1157 assume-screen 100/width, 10/height +1158 # initialize environment +1159 assume-resources [ +1160 ] +1161 env:&:environment <- new-programming-environment resources, screen, [] +1162 render-all screen, env, render +1163 # create a sandbox +1164 assume-console [ +1165 ¦ press ctrl-n +1166 ¦ type [add 1, 1] +1167 ¦ press F4 +1168 ] +1169 event-loop screen, console, env, resources +1170 screen-should-contain [ +1171 ¦ . run (F4) . +1172 ¦ . ╎ . +1173 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. +1174 ¦ . ╎0 edit copy delete . +1175 ¦ . ╎add 1, 1 . +1176 ¦ . ╎2 . +1177 ¦ . ╎─────────────────────────────────────────────────. +1178 ¦ . ╎ . +1179 ] +1180 # hit 'page-down' and 'page-up' a couple of times. sandbox index should be stable +1181 assume-console [ +1182 ¦ press page-down +1183 ] +1184 run [ +1185 ¦ event-loop screen, console, env, resources +1186 ] +1187 # sandbox editor hidden; first sandbox displayed +1188 # cursor moves to first sandbox +1189 screen-should-contain [ +1190 ¦ . run (F4) . +1191 ¦ . ╎─────────────────────────────────────────────────. +1192 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy delete . +1193 ¦ . ╎add 1, 1 . +1194 ¦ . ╎2 . +1195 ¦ . ╎─────────────────────────────────────────────────. +1196 ¦ . ╎ . 1197 ] -1198 run [ -1199 ¦ event-loop screen, console, env, resources -1200 ¦ cursor:char <- copy 9251/␣ -1201 ¦ print screen, cursor -1202 ] -1203 # no change -1204 screen-should-contain [ -1205 ¦ . run (F4) . -1206 ¦ . ╎␣ . -1207 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. -1208 ¦ . ╎0 edit copy delete . -1209 ¦ . ╎add 1, 1 . -1210 ¦ . ╎2 . -1211 ¦ . ╎─────────────────────────────────────────────────. -1212 ¦ . ╎1 edit copy delete . -1213 ¦ . ╎add 2, 2 . -1214 ¦ . ╎4 . +1198 # hit 'page-up' again +1199 assume-console [ +1200 ¦ press page-up +1201 ] +1202 run [ +1203 ¦ event-loop screen, console, env, resources +1204 ] +1205 # back to displaying both sandboxes as well as editor +1206 screen-should-contain [ +1207 ¦ . run (F4) . +1208 ¦ . ╎ . +1209 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. +1210 ¦ . ╎0 edit copy delete . +1211 ¦ . ╎add 1, 1 . +1212 ¦ . ╎2 . +1213 ¦ . ╎─────────────────────────────────────────────────. +1214 ¦ . ╎ . 1215 ] -1216 ] -1217 -1218 scenario scrolling-manages-sandbox-index-correctly [ -1219 local-scope -1220 trace-until 100/app # trace too long -1221 assume-screen 100/width, 10/height -1222 # initialize environment -1223 assume-resources [ -1224 ] -1225 env:&:environment <- new-programming-environment resources, screen, [] -1226 render-all screen, env, render -1227 # create a sandbox -1228 assume-console [ -1229 ¦ press ctrl-n -1230 ¦ type [add 1, 1] -1231 ¦ press F4 -1232 ] -1233 event-loop screen, console, env, resources -1234 screen-should-contain [ -1235 ¦ . run (F4) . -1236 ¦ . ╎ . -1237 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. -1238 ¦ . ╎0 edit copy delete . -1239 ¦ . ╎add 1, 1 . -1240 ¦ . ╎2 . -1241 ¦ . ╎─────────────────────────────────────────────────. -1242 ¦ . ╎ . -1243 ] -1244 # hit 'page-down' and 'page-up' a couple of times. sandbox index should be stable -1245 assume-console [ -1246 ¦ press page-down -1247 ] -1248 run [ -1249 ¦ event-loop screen, console, env, resources -1250 ] -1251 # sandbox editor hidden; first sandbox displayed -1252 # cursor moves to first sandbox -1253 screen-should-contain [ -1254 ¦ . run (F4) . -1255 ¦ . ╎─────────────────────────────────────────────────. -1256 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy delete . -1257 ¦ . ╎add 1, 1 . -1258 ¦ . ╎2 . -1259 ¦ . ╎─────────────────────────────────────────────────. -1260 ¦ . ╎ . -1261 ] -1262 # hit 'page-up' again -1263 assume-console [ -1264 ¦ press page-up -1265 ] -1266 run [ -1267 ¦ event-loop screen, console, env, resources -1268 ] -1269 # back to displaying both sandboxes as well as editor -1270 screen-should-contain [ -1271 ¦ . run (F4) . -1272 ¦ . ╎ . -1273 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎─────────────────────────────────────────────────. -1274 ¦ . ╎0 edit copy delete . -1275 ¦ . ╎add 1, 1 . -1276 ¦ . ╎2 . -1277 ¦ . ╎─────────────────────────────────────────────────. -1278 ¦ . ╎ . -1279 ] -1280 # hit 'page-down' -1281 assume-console [ -1282 ¦ press page-down -1283 ] -1284 run [ -1285 ¦ event-loop screen, console, env, resources -1286 ] -1287 # sandbox editor hidden; first sandbox displayed -1288 # cursor moves to first sandbox -1289 screen-should-contain [ -1290 ¦ . run (F4) . -1291 ¦ . ╎─────────────────────────────────────────────────. -1292 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy delete . -1293 ¦ . ╎add 1, 1 . -1294 ¦ . ╎2 . -1295 ¦ . ╎─────────────────────────────────────────────────. -1296 ¦ . ╎ . -1297 ] -1298 ] +1216 # hit 'page-down' +1217 assume-console [ +1218 ¦ press page-down +1219 ] +1220 run [ +1221 ¦ event-loop screen, console, env, resources +1222 ] +1223 # sandbox editor hidden; first sandbox displayed +1224 # cursor moves to first sandbox +1225 screen-should-contain [ +1226 ¦ . run (F4) . +1227 ¦ . ╎─────────────────────────────────────────────────. +1228 ¦ .╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╎0 edit copy delete . +1229 ¦ . ╎add 1, 1 . +1230 ¦ . ╎2 . +1231 ¦ . ╎─────────────────────────────────────────────────. +1232 ¦ . ╎ . +1233 ] +1234 ] diff --git a/html/edit/007-sandbox-delete.mu.html b/html/edit/007-sandbox-delete.mu.html index 6671e24e..e4e4666d 100644 --- a/html/edit/007-sandbox-delete.mu.html +++ b/html/edit/007-sandbox-delete.mu.html @@ -224,7 +224,7 @@ if ('onhashchange' in window) { 162 ¦ press F4 163 ¦ type [add 1, 1] 164 ¦ press F4 -165 ¦ press page-down +165 ¦ press page-down 166 ] 167 event-loop screen, console, env, resources 168 screen-should-contain [ @@ -271,7 +271,7 @@ if ('onhashchange' in window) { 209 ¦ press F4 210 ¦ type [add 1, 1] 211 ¦ press F4 -212 ¦ press page-down +212 ¦ press page-down 213 ] 214 event-loop screen, console, env, resources 215 screen-should-contain [ @@ -318,8 +318,8 @@ if ('onhashchange' in window) { 256 ¦ press F4 257 ¦ type [add 1, 1] 258 ¦ press F4 -259 ¦ press page-down -260 ¦ press page-down +259 ¦ press page-down +260 ¦ press page-down 261 ] 262 event-loop screen, console, env, resources 263 screen-should-contain [ @@ -384,8 +384,8 @@ if ('onhashchange' in window) { 322 # delete the second sandbox, then try to scroll down twice 323 assume-console [ 324 ¦ left-click 3, 99 -325 ¦ press page-down -326 ¦ press page-down +325 ¦ press page-down +326 ¦ press page-down 327 ] 328 run [ 329 ¦ event-loop screen, console, env, resources diff --git a/html/edit/008-sandbox-edit.mu.html b/html/edit/008-sandbox-edit.mu.html index 76dfb6e9..bdca5bcc 100644 --- a/html/edit/008-sandbox-edit.mu.html +++ b/html/edit/008-sandbox-edit.mu.html @@ -278,8 +278,8 @@ if ('onhashchange' in window) { 216 ¦ press F4 217 ¦ type [add 1, 1] 218 ¦ press F4 -219 ¦ press page-down -220 ¦ press page-down +219 ¦ press page-down +220 ¦ press page-down 221 ] 222 event-loop screen, console, env, resources 223 screen-should-contain [ @@ -364,9 +364,9 @@ if ('onhashchange' in window) { 302 ] 303 # now try to scroll past end 304 assume-console [ -305 ¦ press page-down -306 ¦ press page-down -307 ¦ press page-down +305 ¦ press page-down +306 ¦ press page-down +307 ¦ press page-down 308 ] 309 run [ 310 ¦ event-loop screen, console, env, resources diff --git a/html/edit/009-sandbox-test.mu.html b/html/edit/009-sandbox-test.mu.html index f943dd0f..e10a391e 100644 --- a/html/edit/009-sandbox-test.mu.html +++ b/html/edit/009-sandbox-test.mu.html @@ -164,7 +164,7 @@ if ('onhashchange' in window) { 101 } 102 ] 103 -104 before <end-restore-sandbox> [ +104 before <end-restore-sandbox> [ 105 { 106 ¦ filename <- append filename, [.out] 107 ¦ contents <- slurp resources, filename @@ -252,11 +252,11 @@ if ('onhashchange' in window) { 189 ¦ response-is-expected?:bool <- equal expected-response, sandbox-response 190 ¦ { 191 ¦ ¦ break-if response-is-expected?:bool -192 ¦ ¦ row, screen <- render-text screen, sandbox-response, left, right, 1/red, row +192 ¦ ¦ row, screen <- render-text screen, sandbox-response, left, right, 1/red, row 193 ¦ } 194 ¦ { 195 ¦ ¦ break-unless response-is-expected?:bool -196 ¦ ¦ row, screen <- render-text screen, sandbox-response, left, right, 2/green, row +196 ¦ ¦ row, screen <- render-text screen, sandbox-response, left, right, 2/green, row 197 ¦ } 198 ¦ jump +render-sandbox-end 199 } diff --git a/html/edit/010-sandbox-trace.mu.html b/html/edit/010-sandbox-trace.mu.html index eaeedfcb..39a640a1 100644 --- a/html/edit/010-sandbox-trace.mu.html +++ b/html/edit/010-sandbox-trace.mu.html @@ -307,7 +307,7 @@ if ('onhashchange' in window) { 244 ¦ break-unless display-trace? 245 ¦ sandbox-trace:text <- get *sandbox, trace:offset 246 ¦ break-unless sandbox-trace # nothing to print; move on -247 ¦ row, screen <- render-text screen, sandbox-trace, left, right, 245/grey, row +247 ¦ row, screen <- render-text screen, sandbox-trace, left, right, 245/grey, row 248 } 249 <render-sandbox-trace-done> 250 ] diff --git a/html/edit/011-errors.mu.html b/html/edit/011-errors.mu.html index 9320637f..48f69e14 100644 --- a/html/edit/011-errors.mu.html +++ b/html/edit/011-errors.mu.html @@ -72,7 +72,7 @@ if ('onhashchange' in window) { 9 local-scope 10 load-ingredients 11 recipes:&:editor <- get *env, recipes:offset - 12 in:text <- editor-contents recipes + 12 in:text <- editor-contents recipes 13 resources <- dump resources, [lesson/recipes.mu], in 14 recipe-errors:text <- reload in 15 *env <- put *env, recipe-errors:offset, recipe-errors @@ -99,7 +99,7 @@ if ('onhashchange' in window) { 36 { 37 ¦ recipe-errors:text <- get *env, recipe-errors:offset 38 ¦ break-unless recipe-errors - 39 ¦ row, screen <- render-text screen, recipe-errors, left, right, 1/red, row + 39 ¦ row, screen <- render-text screen, recipe-errors, left, right, 1/red, row 40 } 41 ] 42 @@ -171,7 +171,7 @@ if ('onhashchange' in window) { 108 ¦ sandbox-errors:text <- get *sandbox, errors:offset 109 ¦ break-unless sandbox-errors 110 ¦ *sandbox <- put *sandbox, response-starting-row-on-screen:offset, 0 # no response -111 ¦ row, screen <- render-text screen, sandbox-errors, left, right, 1/red, row +111 ¦ row, screen <- render-text screen, sandbox-errors, left, right, 1/red, row 112 ¦ # don't try to print anything more for this sandbox 113 ¦ jump +render-sandbox-end 114 } diff --git a/html/edit/012-editor-undo.mu.html b/html/edit/012-editor-undo.mu.html index cf98e0dd..af9e02dd 100644 --- a/html/edit/012-editor-undo.mu.html +++ b/html/edit/012-editor-undo.mu.html @@ -1079,7 +1079,7 @@ if ('onhashchange' in window) { 1016 editor-render screen, e 1017 # scroll the page 1018 assume-console [ -1019 ¦ press page-down +1019 ¦ press page-down 1020 ] 1021 editor-event-loop screen, console, e 1022 # undo @@ -1113,7 +1113,7 @@ if ('onhashchange' in window) { 1050 editor-render screen, e 1051 # scroll the page down and up 1052 assume-console [ -1053 ¦ press page-down +1053 ¦ press page-down 1054 ¦ press ctrl-b 1055 ] 1056 editor-event-loop screen, console, e @@ -1148,8 +1148,8 @@ if ('onhashchange' in window) { 1085 editor-render screen, e 1086 # scroll the page down and up 1087 assume-console [ -1088 ¦ press page-down -1089 ¦ press page-up +1088 ¦ press page-down +1089 ¦ press page-up 1090 ] 1091 editor-event-loop screen, console, e 1092 # undo @@ -2029,10 +2029,10 @@ if ('onhashchange' in window) { 1966 ] 1967 ] 1968 -1969 after <delete-to-end-of-line-begin> [ +1969 after <delete-to-end-of-line-begin> [ 1970 top-before:&:duplex-list:char <- get *editor, top-of-screen:offset 1971 ] -1972 before <delete-to-end-of-line-end> [ +1972 before <delete-to-end-of-line-end> [ 1973 { 1974 ¦ break-unless deleted-cells # delete failed; don't add an undo operation 1975 ¦ top-after:&:duplex-list:char <- get *editor, top-of-screen:offset @@ -2132,10 +2132,10 @@ if ('onhashchange' in window) { 2069 ] 2070 ] 2071 -2072 after <delete-to-start-of-line-begin> [ +2072 after <delete-to-start-of-line-begin> [ 2073 top-before:&:duplex-list:char <- get *editor, top-of-screen:offset 2074 ] -2075 before <delete-to-start-of-line-end> [ +2075 before <delete-to-start-of-line-end> [ 2076 { 2077 ¦ break-unless deleted-cells # delete failed; don't add an undo operation 2078 ¦ top-after:&:duplex-list:char <- get *editor, top-of-screen:offset -- cgit 1.4.1-2-gfad0