123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- """
- Key bindings, for scrolling up and down through pages.
- This are separate bindings, because GNU readline doesn't have them, but
- they are very useful for navigating through long multiline buffers, like in
- Vi, Emacs, etc...
- """
- from __future__ import unicode_literals
- from prompt_toolkit.layout.utils import find_window_for_buffer_name
- from six.moves import range
- __all__ = (
- 'scroll_forward',
- 'scroll_backward',
- 'scroll_half_page_up',
- 'scroll_half_page_down',
- 'scroll_one_line_up',
- 'scroll_one_line_down',
- )
- def _current_window_for_event(event):
- """
- Return the `Window` for the currently focussed Buffer.
- """
- return find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
- def scroll_forward(event, half=False):
- """
- Scroll window down.
- """
- w = _current_window_for_event(event)
- b = event.cli.current_buffer
- if w and w.render_info:
- info = w.render_info
- ui_content = info.ui_content
- # Height to scroll.
- scroll_height = info.window_height
- if half:
- scroll_height //= 2
- # Calculate how many lines is equivalent to that vertical space.
- y = b.document.cursor_position_row + 1
- height = 0
- while y < ui_content.line_count:
- line_height = info.get_height_for_line(y)
- if height + line_height < scroll_height:
- height += line_height
- y += 1
- else:
- break
- b.cursor_position = b.document.translate_row_col_to_index(y, 0)
- def scroll_backward(event, half=False):
- """
- Scroll window up.
- """
- w = _current_window_for_event(event)
- b = event.cli.current_buffer
- if w and w.render_info:
- info = w.render_info
- # Height to scroll.
- scroll_height = info.window_height
- if half:
- scroll_height //= 2
- # Calculate how many lines is equivalent to that vertical space.
- y = max(0, b.document.cursor_position_row - 1)
- height = 0
- while y > 0:
- line_height = info.get_height_for_line(y)
- if height + line_height < scroll_height:
- height += line_height
- y -= 1
- else:
- break
- b.cursor_position = b.document.translate_row_col_to_index(y, 0)
- def scroll_half_page_down(event):
- """
- Same as ControlF, but only scroll half a page.
- """
- scroll_forward(event, half=True)
- def scroll_half_page_up(event):
- """
- Same as ControlB, but only scroll half a page.
- """
- scroll_backward(event, half=True)
- def scroll_one_line_down(event):
- """
- scroll_offset += 1
- """
- w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
- b = event.cli.current_buffer
- if w:
- # When the cursor is at the top, move to the next line. (Otherwise, only scroll.)
- if w.render_info:
- info = w.render_info
- if w.vertical_scroll < info.content_height - info.window_height:
- if info.cursor_position.y <= info.configured_scroll_offsets.top:
- b.cursor_position += b.document.get_cursor_down_position()
- w.vertical_scroll += 1
- def scroll_one_line_up(event):
- """
- scroll_offset -= 1
- """
- w = find_window_for_buffer_name(event.cli, event.cli.current_buffer_name)
- b = event.cli.current_buffer
- if w:
- # When the cursor is at the bottom, move to the previous line. (Otherwise, only scroll.)
- if w.render_info:
- info = w.render_info
- if w.vertical_scroll > 0:
- first_line_height = info.get_height_for_line(info.first_visible_line())
- cursor_up = info.cursor_position.y - (info.window_height - 1 - first_line_height -
- info.configured_scroll_offsets.bottom)
- # Move cursor up, as many steps as the height of the first line.
- # TODO: not entirely correct yet, in case of line wrapping and many long lines.
- for _ in range(max(0, cursor_up)):
- b.cursor_position += b.document.get_cursor_up_position()
- # Scroll window
- w.vertical_scroll -= 1
- def scroll_page_down(event):
- """
- Scroll page down. (Prefer the cursor at the top of the page, after scrolling.)
- """
- w = _current_window_for_event(event)
- b = event.cli.current_buffer
- if w and w.render_info:
- # Scroll down one page.
- line_index = max(w.render_info.last_visible_line(), w.vertical_scroll + 1)
- w.vertical_scroll = line_index
- b.cursor_position = b.document.translate_row_col_to_index(line_index, 0)
- b.cursor_position += b.document.get_start_of_line_position(after_whitespace=True)
- def scroll_page_up(event):
- """
- Scroll page up. (Prefer the cursor at the bottom of the page, after scrolling.)
- """
- w = _current_window_for_event(event)
- b = event.cli.current_buffer
- if w and w.render_info:
- # Put cursor at the first visible line. (But make sure that the cursor
- # moves at least one line up.)
- line_index = max(0, min(w.render_info.first_visible_line(),
- b.document.cursor_position_row - 1))
- b.cursor_position = b.document.translate_row_col_to_index(line_index, 0)
- b.cursor_position += b.document.get_start_of_line_position(after_whitespace=True)
- # Set the scroll offset. We can safely set it to zero; the Window will
- # make sure that it scrolls at least until the cursor becomes visible.
- w.vertical_scroll = 0
|