--- /dev/null
+(source gnu)
+(source melpa)
+
+(package-file "compact-docstrings.el")
+
+(development)
--- /dev/null
+EMACS ?= emacs
+CASK = env --unset INSIDE_EMACS EMACS=$(EMACS) cask
+
+screenshot:
+ $(CASK) exec $(EMACS) --debug-init -Q \
+ -L . -l etc/screenshot.el
--- /dev/null
+=============================
+ Compact docstrings in Emacs
+=============================
+
+Shrink blank lines in docstrings and doc comments
+
+.. image:: etc/compact-docstrings.png
+
+Setup
+=====
+
+Enable locally with ``compact-docstrings-mode``::
+
+ (add-hook 'some-mode-hook #'compact-docstrings-mode)
+
+Enable globally (in all programming modes) with ``global-compact-docstrings-mode``::
+
+ (add-hook 'after-init-hook #'global-compact-docstrings-mode)
+
+Customization
+=============
+
+Enable compaction of all comments and strings by setting ``compact-docstrings-only-doc-blocks`` to ``nil``. Change the compact line height by customizing ``compact-docstrings-face``.
--- /dev/null
+;;; compact-docstrings.el --- Shrink blank lines in docstrings and doc comments
+
+;; Copyright (C) 2016 Free Software Foundation, Inc.
+
+;; Author: Clément Pit-Claudel <clement.pitclaudel@live.com>
+;; Maintainer: Clément Pit-Claudel <clement.pitclaudel@live.com>
+;; URL: https://github.com/cpitclaudel/compact-docstrings
+;; Package-Version: 0.1
+;; Keywords: convenience, faces, lisp, maint, c
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Shrink blank lines in docstrings and doc comments
+;;
+;; Enable locally with `compact-docstrings-mode':
+;; (add-hook 'some-mode-hook #'compact-docstrings-mode)
+;;
+;; Enable globally (in all programming modes) with
+;; (add-hook 'after-init-hook #'global-compact-docstrings--mode)
+
+;;; Code:
+
+(defgroup compact-docstrings nil
+ "Shrink empty lines in docstrings and doc comments."
+ :group 'faces)
+
+(defface compact-docstrings-face
+ '((t :height 0.5))
+ "Face applied to blank lines in docstrings."
+ :group 'compact-docstrings)
+
+(defcustom compact-docstrings-only-doc-blocks t
+ "When nil, also shrink blank lines in regular strings and comments."
+ :group 'compact-docstrings
+ :type 'boolean)
+
+(defun compact-docstrings--matcher (bound)
+ "Find blank line in docstring, looking in point .. BOUND."
+ (let ((found nil))
+ (while (and (not found) (re-search-forward "^\\s-*\n" bound t))
+ (let ((syntax (syntax-ppss)))
+ (when (and (or (nth 3 syntax) ;; In string
+ (nth 4 syntax)) ;; In comment
+ (or (not compact-docstrings-only-doc-blocks)
+ (let ((face (get-text-property (point) 'face)))
+ (or (eq face 'font-lock-doc-face)
+ (and (listp face) (memq 'font-lock-doc-face face))))))
+ (setq found t))))
+ found))
+
+(defconst compact-docstrings--keywords
+ '((compact-docstrings--matcher 0 'compact-docstrings-face prepend)) 'append)
+
+;;;###autoload
+(define-minor-mode compact-docstrings-mode
+ "Shrink empty lines in docstrings and doc comments."
+ :lighter " compact"
+ (if compact-docstrings-mode
+ (font-lock-add-keywords nil compact-docstrings--keywords 'append)
+ (font-lock-remove-keywords nil compact-docstrings--keywords))
+ (if (fboundp #'font-lock-flush)
+ (font-lock-flush)
+ (with-no-warnings (font-lock-fontify-buffer))))
+
+(defun compact-docstrings--mode-on ()
+ "Turn on `compact-docstrings-mode', if appropriate."
+ (when (derived-mode-p major-mode #'prog-mode)
+ (compact-docstrings-mode)))
+
+;;;###autoload
+(defalias 'shrink-docstrings #'compact-docstrings--mode-on)
+
+;;;###autoload
+(define-globalized-minor-mode global-compact-docstrings-mode compact-docstrings-mode
+ compact-docstrings--mode-on
+ :init-value nil)
+
+(provide 'compact-docstrings)
+;;; compact-docstrings.el ends here
--- /dev/null
+# With compact docstrings
+def complex(real=0.0, imag=0.0):
+ """Form a complex number.
+
+ Keyword arguments:
+ real -- the real part (default 0.0)
+ imag -- the imaginary part (default 0.0)
+
+ Some more description text, artificially
+ lengthened to make it span two lines.
+
+ Another paragraph.
+ """
+ pass
--- /dev/null
+# With regular docstrings
+def complex(real=0.0, imag=0.0):
+ """Form a complex number.
+
+ Keyword arguments:
+ real -- the real part (default 0.0)
+ imag -- the imaginary part (default 0.0)
+
+ Some more description text, artificially
+ lengthened to make it span two lines.
+
+ Another paragraph.
+ """
+ pass
--- /dev/null
+(defvar my/fringe-width 6)
+
+(defconst my/script-dir
+ (file-name-directory (or load-file-name
+ buffer-file-name)))
+
+(defun my/cleanup ()
+ (dolist (buffer (buffer-list))
+ (kill-buffer buffer)))
+
+(defun my/prepare-UI ()
+ "Prepare UI for taking a screenshot."
+ (ido-mode)
+ (tool-bar-mode -1)
+ (menu-bar-mode -1)
+ (scroll-bar-mode -1)
+ (column-number-mode)
+ (fringe-mode (cons my/fringe-width my/fringe-width))
+ (blink-cursor-mode -1)
+ (setq-default cursor-type 'bar
+ split-width-threshold 80
+ truncate-partial-width-windows t
+ frame-title-format (format "Compact docstrings @ Emacs %s" emacs-version)
+ x-gtk-use-system-tooltips nil)
+ (load-theme 'tango t)
+ ;; (set-face-attribute 'tooltip nil :height 60)
+ (set-face-attribute 'match nil :background "yellow1")
+ (set-face-attribute 'default nil :family "Ubuntu Mono" :height 110)
+ (set-face-attribute 'mode-line nil :foreground "gray60" :background "black")
+ (set-face-attribute 'mode-line-inactive nil :foreground "gray60" :background "#404045")
+ (set-face-attribute 'mode-line-buffer-id nil :foreground "#eab700")
+ (set-fontset-font t 'unicode "Ubuntu Mono")
+ (set-frame-size nil 100 13)
+ (redisplay t))
+
+(defun my/load-package ()
+ "Load package."
+ (package-initialize)
+ (load-library "compact-docstrings"))
+
+(defun my/load-example ()
+ "Prepare files and layout windows."
+ (find-file "etc/before.py")
+ (setq buffer-name "Regular docstrings")
+ (find-file-other-window "after.py")
+ (setq buffer-name "Compact docstrings")
+ (compact-docstrings-mode))
+
+(defun my/prepare-screenshot-1 ()
+ "Prepare for taking a screenshot."
+ (my/prepare-UI)
+ (my/load-package)
+ (my/load-example)
+ (message nil))
+
+(defun my/save-screenshot ()
+ "Save screenshot of current frame."
+ (let ((fname (expand-file-name "compact-docstrings.png" my/script-dir)))
+ (process-lines "import" "-window" (frame-parameter nil 'outer-window-id)
+ fname)
+ (process-lines "mogrify" "-strip" "-matte"
+ "-bordercolor" (face-attribute 'fringe :background)
+ "-border" (format "0x%d" my/fringe-width) fname)
+ (process-lines "optipng" "-o3" fname))
+ (kill-emacs))
+
+(defun my/take-screenshot ()
+ (my/prepare-screenshot-1)
+ (redisplay t)
+ (run-with-idle-timer 1 nil #'my/save-screenshot))
+
+(print default-directory)
+(run-with-idle-timer 0 nil #'my/take-screenshot)