               ;; Recreate output window.
               (live-py-show-output-window))
             (set-window-buffer live-py-output-window live-py-output-buffer)
-            (live-py-synchronize-scroll window-start-pos point-line-nr))
+            (live-py-synchronize-scroll
+             (line-number-at-pos window-start-pos) point-line-nr))
         ;; Recreate output buffer and if necessary the output window.
         (live-py-trace)))))
 

(defvar live-py-output-window)
(defvar live-py-driver)
(defvar live-py-module)
(defvar live-py-dir)
(defvar live-py-path)
(defvar live-py-version)

         (reused-buffer (buffer-live-p
                         (and live-py-output-buffer
                              (get-buffer live-py-output-buffer)))))
    (save-restriction
      (widen)
      ;; Create (or recreate) if necessary, update and last but not least
      ;; display output buffer.
      (shell-command-on-region 1
                               (1+ (buffer-size))
                               command-line
                               live-py-output-buffer))
    (with-current-buffer live-py-output-buffer
      (setq buffer-read-only 1)
      (unless reused-buffer (toggle-truncate-lines 1)))
    (live-py-synchronize-scroll
     (line-number-at-pos (window-start)) (line-number-at-pos))
    (set 'live-py-timer nil)))

(defun live-py-synchronize-scroll (window-start-line-nr point-line-nr)
  "Synchronize scrolling between Python and output buffer.

Pass the possibly reused (line-number-at-pos (window-start)) to
WINDOW-START-LINE-NR and (line-number-at-pos) to POINT-LINE-NR,
both are relative to (point-min). Numbering starts at 1 for all
*-LINE-NR in this function signature and body.

When the Python buffer is narrowed the output buffer remains
aligned but will not hide the part after the narrowing."
  (let ((point-min-pos (point-min))
        (point-min-line-nr 1))
    (unless (= 1 point-min-pos)
      ;; Compensate for narrowing.
      (save-restriction
        (widen)
        (setq point-min-line-nr (line-number-at-pos point-min-pos))))
    (unless (window-valid-p live-py-output-window)
      ;; Recreate output window.
      (live-py-show-output-window))
    (with-selected-window live-py-output-window
      (goto-char 1)
      (forward-line (+ point-min-line-nr window-start-line-nr -2))
      (recenter-top-bottom 0)
      (forward-line (- point-line-nr window-start-line-nr)))))

(defun live-py-check-to-scroll ()
  "Check if window start or point have to be synchronized."
  ;; Take extra care to not let this function run into a non-handled error.
  ;; On such an error the debugger will not be entered to not block Emacs
  ;; interactivity when `debug-on-error' is active, so it is easily possible
  ;; to miss the error. And on such an error the function will be removed
  ;; from `post-command-hook' which can be quite confusing.

  ;; `window-start' is for some reason not up to date after
  ;; `post-command-hook' in at least these situations:
  ;; - For a few commands like `narrow-to-region' or `viper-goto-line'.
  ;; - Repeated `next-line' towards the end of the Python buffer: The output
  ;;   buffer suddenly lags one line behind.
  ;; See also "calculating new window-start/end without redisplay"
  ;; http://stackoverflow.com/questions/23923371 )
  (when (memq this-command '(narrow-to-region next-line viper-goto-line))
    (redisplay))
  (let ((window-start-pos (window-start))
        (point-line-nr (line-number-at-pos)))
    (unless (and (= live-py-window-start-pos window-start-pos)
