| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent c5043dc commit 089e6f6
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -653,6 +653,131 @@ Windows and pads | |||
| 653 | 653 | is to be displayed. | |
| 654 | 654 | ||
| 655 | 655 | ||
| 656 | + Soft labels | ||
| 657 | + ~~~~~~~~~~~ | ||
| 658 | + | ||
| 659 | + .. _curses-slk: | ||
| 660 | + | ||
| 661 | + The following functions manage *soft-label keys*, a row of labels displayed | ||
| 662 | + along the bottom line of the screen, typically used to label a row of function | ||
| 663 | + keys. :func:`slk_init` must be called before :func:`initscr` or | ||
| 664 | + :func:`newterm`; it takes one screen line away from the standard window for the | ||
| 665 | + labels. | ||
| 666 | + | ||
| 667 | + | ||
| 668 | + .. function:: slk_init(fmt=0) | ||
| 669 | + | ||
| 670 | + Reserve a screen line for the soft labels and choose their layout. *fmt* | ||
| 671 | + selects the arrangement: ``0`` for 3-2-3 (eight labels), ``1`` for 4-4 | ||
| 672 | + (eight labels). Where the underlying curses library supports them, ``2`` | ||
| 673 | + gives 4-4-4 (twelve labels) and ``3`` gives 4-4-4 with an index line. | ||
| 674 | + | ||
| 675 | + Must be called before :func:`initscr` or :func:`newterm`. | ||
| 676 | + | ||
| 677 | + .. versionadded:: next | ||
| 678 | + | ||
| 679 | + | ||
| 680 | + .. function:: slk_set(labnum, label, justify) | ||
| 681 | + | ||
| 682 | + Set the text of soft label number *labnum*, in the range ``1`` through ``8`` | ||
| 683 | + (or ``12`` in a twelve-label layout). *justify* controls how *label* is | ||
| 684 | + placed within the label: ``0`` for left, ``1`` for centered, ``2`` for right. | ||
| 685 | + | ||
| 686 | + .. versionadded:: next | ||
| 687 | + | ||
| 688 | + | ||
| 689 | + .. function:: slk_label(labnum) | ||
| 690 | + | ||
| 691 | + Return the current text of soft label number *labnum*, justified as it was | ||
| 692 | + set, or an empty string if it has no label. | ||
| 693 | + | ||
| 694 | + .. versionadded:: next | ||
| 695 | + | ||
| 696 | + | ||
| 697 | + .. function:: slk_refresh() | ||
| 698 | + | ||
| 699 | + Update the soft labels on the physical screen, like | ||
| 700 | + :meth:`~curses.window.refresh` for a window. | ||
| 701 | + | ||
| 702 | + .. versionadded:: next | ||
| 703 | + | ||
| 704 | + | ||
| 705 | + .. function:: slk_noutrefresh() | ||
| 706 | + | ||
| 707 | + Update the soft labels on the virtual screen, like | ||
| 708 | + :meth:`window.noutrefresh`. Use it together with :func:`doupdate` to batch | ||
| 709 | + screen updates. | ||
| 710 | + | ||
| 711 | + .. versionadded:: next | ||
| 712 | + | ||
| 713 | + | ||
| 714 | + .. function:: slk_clear() | ||
| 715 | + | ||
| 716 | + Remove the soft labels from the screen. | ||
| 717 | + | ||
| 718 | + .. versionadded:: next | ||
| 719 | + | ||
| 720 | + | ||
| 721 | + .. function:: slk_restore() | ||
| 722 | + | ||
| 723 | + Restore the soft labels to the screen after a :func:`slk_clear`. | ||
| 724 | + | ||
| 725 | + .. versionadded:: next | ||
| 726 | + | ||
| 727 | + | ||
| 728 | + .. function:: slk_touch() | ||
| 729 | + | ||
| 730 | + Force all the soft labels to be redrawn by the next :func:`slk_refresh` or | ||
| 731 | + :func:`slk_noutrefresh`. | ||
| 732 | + | ||
| 733 | + .. versionadded:: next | ||
| 734 | + | ||
| 735 | + | ||
| 736 | + .. function:: slk_attron(attr) | ||
| 737 | + slk_attroff(attr) | ||
| 738 | + slk_attrset(attr) | ||
| 739 | + | ||
| 740 | + Add, remove, or set the attributes used to display the soft labels, given as | ||
| 741 | + packed ``A_*`` attributes. | ||
| 742 | + | ||
| 743 | + .. versionadded:: next | ||
| 744 | + | ||
| 745 | + | ||
| 746 | + .. function:: slk_attr() | ||
| 747 | + | ||
| 748 | + Return the current attributes of the soft labels as packed ``A_*`` | ||
| 749 | + attributes. Availability depends on the underlying curses library. | ||
| 750 | + | ||
| 751 | + .. versionadded:: next | ||
| 752 | + | ||
| 753 | + | ||
| 754 | + .. function:: slk_attr_on(attr) | ||
| 755 | + slk_attr_off(attr) | ||
| 756 | + | ||
| 757 | + Turn the given attributes on or off without affecting any others. Like the | ||
| 758 | + ``attr_*`` window methods, these work with the | ||
| 759 | + :ref:`WA_* attributes <curses-wa-constants>` rather than packed ``A_*`` | ||
| 760 | + attributes. | ||
| 761 | + | ||
| 762 | + .. versionadded:: next | ||
| 763 | + | ||
| 764 | + | ||
| 765 | + .. function:: slk_attr_set(attr, pair=0) | ||
| 766 | + | ||
| 767 | + Set the attributes and color pair of the soft labels. *attr* is given as | ||
| 768 | + :ref:`WA_* attributes <curses-wa-constants>` and *pair* as a color pair | ||
| 769 | + number. | ||
| 770 | + | ||
| 771 | + .. versionadded:: next | ||
| 772 | + | ||
| 773 | + | ||
| 774 | + .. function:: slk_color(pair) | ||
| 775 | + | ||
| 776 | + Set the color pair of the soft labels to color pair number *pair*. | ||
| 777 | + | ||
| 778 | + .. versionadded:: next | ||
| 779 | + | ||
| 780 | + | ||
| 656 | 781 | Saving and restoring | |
| 657 | 782 | ~~~~~~~~~~~~~~~~~~~~ | |
| 658 | 783 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -182,6 +182,18 @@ curses | |||
| 182 | 182 | :func:`~curses.scr_set`, which dump the whole screen to a file and restore it. | |
| 183 | 183 | (Contributed by Serhiy Storchaka in :gh:`152260`.) | |
| 184 | 184 | ||
| 185 | + * Add the soft-label-key functions to the :mod:`curses` module, which manage a | ||
| 186 | + row of labels along the bottom line of the screen: | ||
| 187 | + :func:`~curses.slk_init`, :func:`~curses.slk_set`, :func:`~curses.slk_label`, | ||
| 188 | + :func:`~curses.slk_refresh`, :func:`~curses.slk_noutrefresh`, | ||
| 189 | + :func:`~curses.slk_clear`, :func:`~curses.slk_restore`, | ||
| 190 | + :func:`~curses.slk_touch`, the attribute functions | ||
| 191 | + :func:`~curses.slk_attron`, :func:`~curses.slk_attroff`, | ||
| 192 | + :func:`~curses.slk_attrset`, :func:`~curses.slk_attr`, | ||
| 193 | + :func:`~curses.slk_attr_on`, :func:`~curses.slk_attr_off`, | ||
| 194 | + :func:`~curses.slk_attr_set`, and :func:`~curses.slk_color`. | ||
| 195 | + (Contributed by Serhiy Storchaka in :gh:`152263`.) | ||
| 196 | + | ||
| 185 | 197 | * Add the :func:`curses.term_attrs` function, which returns the supported | |
| 186 | 198 | video attributes as :ref:`WA_* <curses-wa-constants>` values, the | |
| 187 | 199 | counterpart of :func:`curses.termattrs`. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2843,16 +2843,12 @@ def test_move_down(self): | |||
| 2843 | 2843 | self.mock_win.reset_mock() | |
| 2844 | 2844 | ||
| 2845 | 2845 | ||
| 2846 | - @unittest.skipUnless(hasattr(curses, 'newterm'), 'requires curses.newterm()') | ||
| 2847 | - @unittest.skipIf(not term or term == 'unknown', | ||
| 2848 | - "$TERM=%r, newterm() may not work" % term) | ||
| 2849 | - @unittest.skipIf(sys.platform == "cygwin", | ||
| 2850 | - "cygwin's curses mostly just hangs") | ||
| 2851 | - class ScreenTests(unittest.TestCase): | ||
| 2852 | - # newterm()/set_term() mutate global curses state, but each test drives its | ||
| 2853 | - # own pseudo-terminal(s) and never touches the screen shared by TestCurses, | ||
| 2854 | - # whose setUp() makes that screen current again. So these can run in this | ||
| 2855 | - # process, without a real terminal and without a subprocess. | ||
| 2846 | + class NewtermTestBase(unittest.TestCase): | ||
| 2847 | + # Shared plumbing for tests that drive newterm() over their own | ||
| 2848 | + # pseudo-terminal(s). newterm()/set_term() mutate global curses state, but | ||
| 2849 | + # each test never touches the screen shared by TestCurses, whose setUp() | ||
| 2850 | + # makes that screen current again. So these can run in this process, | ||
| 2851 | + # without a real terminal and without a subprocess. | ||
| 2856 | 2852 | ||
| 2857 | 2853 | def setUp(self): | |
| 2858 | 2854 | # newterm() may install signal handlers; restore them afterwards. | |
@@ -2906,6 +2902,14 @@ def stop_reader(): | |||
| 2906 | 2902 | self.addCleanup(stop_reader) | |
| 2907 | 2903 | return slave | |
| 2908 | 2904 | ||
| 2905 | + | ||
| 2906 | + @unittest.skipUnless(hasattr(curses, 'newterm'), 'requires curses.newterm()') | ||
| 2907 | + @unittest.skipIf(not term or term == 'unknown', | ||
| 2908 | + f"$TERM={term!r}, newterm() may not work") | ||
| 2909 | + @unittest.skipIf(sys.platform == "cygwin", | ||
| 2910 | + "cygwin's curses mostly just hangs") | ||
| 2911 | + class ScreenTests(NewtermTestBase): | ||
| 2912 | + | ||
| 2909 | 2913 | def test_newterm(self): | |
| 2910 | 2914 | s = self.make_pty() | |
| 2911 | 2915 | screen = curses.newterm('xterm', s, s) | |
@@ -2979,5 +2983,100 @@ def test_disallow_instantiation(self): | |||
| 2979 | 2983 | check_disallow_instantiation(self, curses.screen) | |
| 2980 | 2984 | ||
| 2981 | 2985 | ||
| 2986 | + @unittest.skipUnless(hasattr(curses, 'slk_init'), 'requires curses.slk_init()') | ||
| 2987 | + @unittest.skipUnless(hasattr(curses, 'newterm'), 'requires curses.newterm()') | ||
| 2988 | + @unittest.skipIf(not term or term == 'unknown', | ||
| 2989 | + f"$TERM={term!r}, newterm() may not work") | ||
| 2990 | + @unittest.skipIf(sys.platform == "cygwin", | ||
| 2991 | + "cygwin's curses mostly just hangs") | ||
| 2992 | + class SLKTests(NewtermTestBase): | ||
| 2993 | + # Soft-label keys reserve the bottom screen line for a row of labels. | ||
| 2994 | + # slk_init() must run before newterm()/initscr(), so each test sets up its | ||
| 2995 | + # own screen rather than reusing the one TestCurses builds in setUp(). | ||
| 2996 | + | ||
| 2997 | + def make_slk_screen(self, fmt=0): | ||
| 2998 | + s = self.make_pty() | ||
| 2999 | + curses.slk_init(fmt) | ||
| 3000 | + return curses.newterm('xterm', s, s) | ||
| 3001 | + | ||
| 3002 | + def test_init_reserves_a_line(self): | ||
| 3003 | + # Every layout takes the bottom line for the labels; the index-line | ||
| 3004 | + # layout (3) takes a second line for the index. Layouts 0 and 1 are | ||
| 3005 | + # standard; 2 and 3 are ncurses extensions that other curses | ||
| 3006 | + # implementations reject (slk_init() then returns an error). | ||
| 3007 | + ncurses = hasattr(curses, 'ncurses_version') | ||
| 3008 | + for fmt, lines in [(0, 23), (1, 23), (2, 23), (3, 22)]: | ||
| 3009 | + with self.subTest(fmt=fmt): | ||
| 3010 | + try: | ||
| 3011 | + screen = self.make_slk_screen(fmt) | ||
| 3012 | + except curses.error: | ||
| 3013 | + if ncurses or fmt < 2: | ||
| 3014 | + raise | ||
| 3015 | + continue | ||
| 3016 | + self.assertEqual(screen.stdscr.getmaxyx()[0], lines) | ||
| 3017 | + curses.endwin() | ||
| 3018 | + | ||
| 3019 | + def test_init_bad_format(self): | ||
| 3020 | + for fmt in (-1, 4): | ||
| 3021 | + self.assertRaises(ValueError, curses.slk_init, fmt) | ||
| 3022 | + | ||
| 3023 | + def test_set_and_label(self): | ||
| 3024 | + self.make_slk_screen() | ||
| 3025 | + curses.slk_set(1, 'Help', 0) | ||
| 3026 | + curses.slk_set(2, 'Save', 1) | ||
| 3027 | + curses.slk_set(3, 'Quit', 2) | ||
| 3028 | + self.assertEqual(curses.slk_label(1), 'Help') | ||
| 3029 | + self.assertEqual(curses.slk_label(2), 'Save') | ||
| 3030 | + self.assertEqual(curses.slk_label(3), 'Quit') | ||
| 3031 | + | ||
| 3032 | + def test_set_wide(self): | ||
| 3033 | + screen = self.make_slk_screen() | ||
| 3034 | + label = 'Ångström' | ||
| 3035 | + try: | ||
| 3036 | + label.encode(screen.stdscr.encoding) | ||
| 3037 | + except UnicodeEncodeError: | ||
| 3038 | + self.skipTest('the locale cannot encode %r' % label) | ||
| 3039 | + curses.slk_set(1, label, 0) | ||
| 3040 | + self.assertEqual(curses.slk_label(1), label) | ||
| 3041 | + | ||
| 3042 | + def test_set_bad_justify(self): | ||
| 3043 | + self.make_slk_screen() | ||
| 3044 | + for justify in (-1, 3): | ||
| 3045 | + self.assertRaises(ValueError, curses.slk_set, 1, 'x', justify) | ||
| 3046 | + | ||
| 3047 | + def test_refresh(self): | ||
| 3048 | + self.make_slk_screen() | ||
| 3049 | + curses.slk_set(1, 'Help', 0) | ||
| 3050 | + curses.slk_noutrefresh() | ||
| 3051 | + curses.slk_refresh() | ||
| 3052 | + curses.slk_clear() | ||
| 3053 | + curses.slk_restore() | ||
| 3054 | + curses.slk_touch() | ||
| 3055 | + | ||
| 3056 | + def test_attributes(self): | ||
| 3057 | + self.make_slk_screen() | ||
| 3058 | + curses.slk_attron(curses.A_BOLD) | ||
| 3059 | + curses.slk_attrset(curses.A_UNDERLINE) | ||
| 3060 | + curses.slk_attroff(curses.A_BOLD) | ||
| 3061 | + if hasattr(curses, 'slk_attr'): | ||
| 3062 | + self.assertIsInstance(curses.slk_attr(), int) | ||
| 3063 | + | ||
| 3064 | + def test_attr_on_off(self): | ||
| 3065 | + self.make_slk_screen() | ||
| 3066 | + curses.slk_attr_on(curses.A_BOLD) | ||
| 3067 | + curses.slk_attr_off(curses.A_BOLD) | ||
| 3068 | + | ||
| 3069 | + def test_color(self): | ||
| 3070 | + # slk_attr_set() and slk_color() act on a color pair, so the color | ||
| 3071 | + # subsystem must be started first. | ||
| 3072 | + self.make_slk_screen() | ||
| 3073 | + if not curses.has_colors(): | ||
| 3074 | + self.skipTest('requires colors support') | ||
| 3075 | + curses.start_color() | ||
| 3076 | + curses.slk_attr_set(curses.A_BOLD) | ||
| 3077 | + curses.slk_attr_set(curses.A_BOLD, 0) | ||
| 3078 | + curses.slk_color(0) | ||
| 3079 | + | ||
| 3080 | + | ||
| 2982 | 3081 | if __name__ == '__main__': | |
| 2983 | 3082 | unittest.main() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,9 @@ | |||
| 1 | + Add the soft-label-key functions to the :mod:`curses` module: | ||
| 2 | + :func:`~curses.slk_init`, :func:`~curses.slk_set`, :func:`~curses.slk_label`, | ||
| 3 | + :func:`~curses.slk_refresh`, :func:`~curses.slk_noutrefresh`, | ||
| 4 | + :func:`~curses.slk_clear`, :func:`~curses.slk_restore`, | ||
| 5 | + :func:`~curses.slk_touch`, :func:`~curses.slk_attron`, | ||
| 6 | + :func:`~curses.slk_attroff`, :func:`~curses.slk_attrset`, | ||
| 7 | + :func:`~curses.slk_attr`, :func:`~curses.slk_attr_on`, | ||
| 8 | + :func:`~curses.slk_attr_off`, :func:`~curses.slk_attr_set` and | ||
| 9 | + :func:`~curses.slk_color`. | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments