def navigate(self, rows, cols):
        """Jump number of rows and columns provided.

        Use in normal mode.

        Parameters
        ==========
        rows, cols (integers)
            represent how many rows and columns the cursor
            should be moved; the signal indicates the
            direction of the movement;
        """
        ### store current row and column

        current_row = self.row
        current_col = self.col

        ### clamp final row value so it is within existing
        ### lines indices (since row number represents index
        ### of current line)

        max_row_index = len(self.lines) - 1

        self.row = new_row = max(min(max_row_index, current_row + rows), 0)

        ### calculate how many rows we will move
        no_of_rows_to_move = new_row - current_row

        ### update our visible row index with the number of
        ### rows moved
        self.visible_row += no_of_rows_to_move

        ### if cursor...

        if (
            ### will move rows up
            no_of_rows_to_move < 0
            ### and end up in a line above the visible ones
            and self.visible_row < 0
        ):

            ## adjust the visible row index to 0, so the
            ## cursor ends up at the top visible row
            self.visible_row = 0

            ## make it so the new top visible line is the
            ## one indicated by the 'new_row' index
            self.top_visible_line_index = new_row

            ## now that you have a new top visible line
            ## set, update the visible lines
            self.update_visible_lines()

        ### otherwise, if cursor...

        elif (
            ### will move moved rows down
            no_of_rows_to_move > 0
            ### and end up in a line below the visible ones
            and self.visible_row >= NUMBER_OF_VISIBLE_LINES
        ):

            ## adjust the visible row index to the number
            ## of visible lines minus one, so the
            ## cursor ends up at the bottom visible row
            self.visible_row = NUMBER_OF_VISIBLE_LINES - 1

            ## make it so the new top visible line is the
            ## one 'x' rows behind the new row, where x equals
            ## the number of visible lines plus 1
            self.top_visible_line_index = new_row - NUMBER_OF_VISIBLE_LINES + 1

            ## now that you have a new top visible line
            ## set, update the visible lines
            self.update_visible_lines()

        ### clamp final colum value so it's within
        ### existing characters indices (since column number
        ### represents index of current character)

        max_col_index = len(self.lines[new_row]) - 1

        self.col = max(min(max_col_index, current_col + cols), 0)

        ### admin task: snap cursor to new row and column
        ### defined, also making it assume the size of the
        ### character where it sits (if there is one)

        ## try retrieving character sitting at the visible
        ## row and column we just defined

        try:
            char_obj = self.visible_lines[self.visible_row][self.col]

        ## if an IndexError occurs, it means that there is
        ## no character where the cursor sits, which we
        ## assume it is so because the line is empty, so we
        ## just place the cursor at the beginning of the line

        except IndexError:
            self.rect.topleft = self.visible_lines[self.visible_row].rect.topleft

        ## if we otherwise succeed in retrieving the char
        ## in the current column, we move the cursor to the
        ## position of that character object;
        ##
        ## we also update the cursor size to that of the
        ## character obj

        else:

            self.rect.topleft = char_obj.rect.topleft
            self.rect.size = char_obj.rect.size
Jump number of rows and columns provided.

        Use in normal mode.

        Parameters
        ==========
        rows, cols (integers)
            represent how many rows and columns the cursor
            should be moved; the signal indicates the
            direction of the movement;
        
nodezator/textman/editor/cursor/navigation.py