├── .README.md.texinfo.pandoc ├── .gitignore ├── Eldev ├── LICENSE ├── README.md ├── pre-commit ├── test ├── test-helper.el └── writeroom-mode-test.el ├── texi-before-body ├── writeroom-mode.el ├── writeroom-mode.info └── writeroom-mode.png /.README.md.texinfo.pandoc: -------------------------------------------------------------------------------- 1 | ;; -*- mode: emacs-lisp -*- 2 | 3 | ;; pandoc-mode settings settings file 4 | ;; saved on 2014.02.13 10:33 5 | 6 | ((html-q-tags) 7 | (no-tex-ligatures) 8 | (old-dashes) 9 | (atx-headers) 10 | (ascii) 11 | (biblatex) 12 | (natbib) 13 | (table-of-contents) 14 | (no-highlight) 15 | (no-wrap) 16 | (section-divs) 17 | (listings) 18 | (number-sections) 19 | (chapters) 20 | (self-contained) 21 | (incremental) 22 | (gladtex) 23 | (smart) 24 | (parse-raw) 25 | (reference-links) 26 | (normalize) 27 | (strict) 28 | (preserve-tabs) 29 | (standalone . t) 30 | (read . "markdown_github") 31 | (read-lhs) 32 | (read-extensions 33 | ("abbreviations") 34 | ("all_symbols_escapable") 35 | ("ascii_identifiers") 36 | ("auto_identifiers") 37 | ("autolink_bare_uris") 38 | ("backtick_code_blocks") 39 | ("blank_before_blockquote") 40 | ("blank_before_header") 41 | ("citations") 42 | ("definition_lists") 43 | ("escaped_line_breaks") 44 | ("example_lists") 45 | ("fancy_lists") 46 | ("fenced_code_attributes") 47 | ("fenced_code_blocks") 48 | ("footnotes") 49 | ("grid_tables") 50 | ("hard_line_breaks") 51 | ("header_attributes") 52 | ("ignore_line_breaks") 53 | ("implicit_figures") 54 | ("implicit_header_references") 55 | ("inline_code_attributes") 56 | ("inline_notes") 57 | ("intraword_underscores") 58 | ("latex_macros") 59 | ("line_blocks") 60 | ("link_attributes") 61 | ("lists_without_preceding_blankline") 62 | ("markdown_attribute") 63 | ("markdown_in_html_blocks") 64 | ("mmd_header_identifiers") 65 | ("mmd_title_block") 66 | ("multiline_tables") 67 | ("pandoc_title_block") 68 | ("pipe_tables") 69 | ("raw_html") 70 | ("raw_tex") 71 | ("simple_tables") 72 | ("startnum") 73 | ("strikeout") 74 | ("subscript") 75 | ("superscript") 76 | ("table_captions") 77 | ("tex_math_dollars") 78 | ("tex_math_double_backslash") 79 | ("tex_math_single_backslash") 80 | ("yaml_metadata_block")) 81 | (write . "texinfo") 82 | (write-lhs) 83 | (write-extensions 84 | ("abbreviations") 85 | ("all_symbols_escapable") 86 | ("ascii_identifiers") 87 | ("auto_identifiers") 88 | ("autolink_bare_uris") 89 | ("backtick_code_blocks") 90 | ("blank_before_blockquote") 91 | ("blank_before_header") 92 | ("citations") 93 | ("definition_lists") 94 | ("escaped_line_breaks") 95 | ("example_lists") 96 | ("fancy_lists") 97 | ("fenced_code_attributes") 98 | ("fenced_code_blocks") 99 | ("footnotes") 100 | ("grid_tables") 101 | ("hard_line_breaks") 102 | ("header_attributes") 103 | ("ignore_line_breaks") 104 | ("implicit_figures") 105 | ("implicit_header_references") 106 | ("inline_code_attributes") 107 | ("inline_notes") 108 | ("intraword_underscores") 109 | ("latex_macros") 110 | ("line_blocks") 111 | ("link_attributes") 112 | ("lists_without_preceding_blankline") 113 | ("markdown_attribute") 114 | ("markdown_in_html_blocks") 115 | ("mmd_header_identifiers") 116 | ("mmd_title_block") 117 | ("multiline_tables") 118 | ("pandoc_title_block") 119 | ("pipe_tables") 120 | ("raw_html") 121 | ("raw_tex") 122 | ("simple_tables") 123 | ("startnum") 124 | ("strikeout") 125 | ("subscript") 126 | ("superscript") 127 | ("table_captions") 128 | ("tex_math_dollars") 129 | ("tex_math_double_backslash") 130 | ("tex_math_single_backslash") 131 | ("yaml_metadata_block")) 132 | (output . "writeroom-mode.texi") 133 | (data-dir) 134 | (output-dir) 135 | (template) 136 | (css) 137 | (reference-odt) 138 | (reference-docx) 139 | (epub-metadata) 140 | (epub-stylesheet) 141 | (epub-cover-image) 142 | (csl) 143 | (citation-abbreviations) 144 | (include-in-header) 145 | (include-before-body . "~/src/writeroom-mode/texi-before-body") 146 | (include-after-body) 147 | (epub-embed-font) 148 | (filter) 149 | (bibliography) 150 | (variable) 151 | (metadata) 152 | (latex-engine) 153 | (email-obfuscation) 154 | (columns) 155 | (tab-stop) 156 | (base-header-level) 157 | (slide-level) 158 | (toc-depth) 159 | (epub-chapter-level) 160 | (latexmathml) 161 | (mathml) 162 | (mimetex) 163 | (webtex) 164 | (jsmath) 165 | (mathjax) 166 | (title-prefix) 167 | (id-prefix) 168 | (indented-code-classes) 169 | (highlight-style) 170 | (number-offset) 171 | (default-image-extension)) 172 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /writeroom-mode.elc 2 | /writeroom-mode.texi 3 | 4 | # Added automatically by ‘eldev init’. 5 | /.eldev 6 | /Eldev-local 7 | -------------------------------------------------------------------------------- /Eldev: -------------------------------------------------------------------------------- 1 | ;; -*- mode: emacs-lisp; lexical-binding: t -*- 2 | 3 | (eldev-use-local-dependency "~/src/visual-fill-column") 4 | 5 | ;; Autodetermined by `eldev init'. 6 | (eldev-use-package-archive 'nongnu-elpa) 7 | 8 | (eldev-use-plugin 'autoloads) 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2012-2022, Joost Kremers 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Writeroom-mode # 2 | 3 | `writeroom-mode` is a minor mode for Emacs that implements a distraction-free writing mode similar to the famous Writeroom editor for OS X. `writeroom-mode` is meant for GNU Emacs 24, lower versions are not actively supported. 4 | 5 | 6 | ## Installation ## 7 | 8 | `writeroom-mode` can be installed through the package manager from [Melpa](http://melpa.org/). If installing manually, make sure to also install its dependency [`visual-fill-column`](https://github.com/joostkremers/visual-fill-column). 9 | 10 | 11 | ## Usage ## 12 | 13 | `writeroom-mode` can be activated in a buffer by calling `M-x writeroom-mode RET`. A screen shot can probably explain best what `writeroom-mode` does. In the default configuration, after activating `writeroom-mode`, your screen looks like this (modulo the colour theme, of course): 14 | 15 | ![screenshot](writeroom-mode.png) 16 | 17 | By default, `writeroom-mode` does the following things: 18 | 19 | * activate fullscreen 20 | * disable transparency 21 | * disable the menu bar 22 | * disable the tool bar 23 | * disable the scroll bar 24 | * enable a bottom window divider of 1 pixel 25 | * maximise the current window (i.e., delete all other windows in the frame) 26 | * place the fringes outside the margins 27 | * disable the mode line 28 | * add window margins to the current buffer so that the text is 80 characters wide 29 | 30 | The last three effects are buffer-local. The other effects apply to the current frame. Because `writeroom-mode` is a minor mode, this isn't entirely on the up and up, since minor modes aren't supposed to have such global effects. But `writeroom-mode` is meant for distraction-free writing, so these effects do make sense. 31 | 32 | All these effects can be disabled or customised. In addition, there are several more options that are disabled by default but can be enabled in the [customisation buffer](#customisation). 33 | 34 | 35 | ## Multiple writeroom-mode buffers ## 36 | 37 | It is possible to activate `writeroom-mode` in more than one buffer. The global effects are of course activated only once and they remain active until `writeroom-mode` is deactivated in *all* buffers. Alternatively, if you wish to use `writeroom-mode` in all buffers that have a particular major mode (e.g., `text-mode`, `markdown-mode`), you can use the global minor mode `global-writeroom-mode`. This function enables the global effects and activates the buffer-local effects in all (current and future) buffers that have a major mode listed in the user option `writeroom-major-modes` (by default only `text-mode`). 38 | 39 | When `global-writeroom-mode` is active, the function `writeroom-mode` can still be called to enable or disable `writeroom-mode` in individual buffers (regardless of their major mode, of course). Calling `global-writeroom-mode` again disables `writeroom-mode` in all buffers in which it is active, also those in which it was activated manually. 40 | 41 | 42 | ## Frame effects ## 43 | 44 | Most of the global effects that `writeroom-mode` enables are handled by setting specific frame parameters. This means that they apply to the current frame. If you switch to another frame and display a `writeroom-mode` buffer, only the buffer-local effects will be visible. 45 | 46 | `writeroom-mode` tries to make sure that it only affects one frame, and that it restores that particular frame when it is deactivated in the last buffer. This means it should be safe to activate `writeroom-mode` in one frame and deactivate it in another. Killing the `writeroom-mode` frame should also be safe. 47 | 48 | The affected frame is always restored to its original state, before `writeroom-mode` was activated, even if you change any of the frame parameters manually while `writeroom-mode` is active. 49 | 50 | 51 | ## Customisation ## 52 | 53 | The customisation buffer for `writeroom-mode` can be opened with `M-x customize-group RET writeroom RET`. It provides the options listed below. 54 | 55 | 56 | ### Added Width Left ### 57 | 58 | Extra columns added to the left side of the text area. These columns are added after the text area is centred, so that the text area is essentially off-set to the left by the amount provided. This can be an integer or a function of no arguments that should return an integer. By default, this is used to accommodate line numbers if `display-line-numbers-mode` is active, so that the actual text is still centred. 59 | 60 | 61 | ### Border Width ### 62 | 63 | Width of the border around the text area. Disabled by default, see `writeroom-global-effects` to enable the border. 64 | 65 | 66 | ### Bottom Divider Width ### 67 | 68 | Width in pixels of the bottom window divider. Default value is 1. The bottom window divider helps in distinguishing the minibuffer from the text area, and also in distinguishing two windows split top-to-bottom. 69 | 70 | 71 | ### Extra Line Spacing ### 72 | 73 | Increase the line spacing. Can be an absolute value (the number of pixels to add to the line) or a number relative to the default line height. Disabled by default. 74 | 75 | 76 | ### Fringes Outside Margins ### 77 | 78 | If set, place the fringes outside the margins. `writeroom-mode` expands the window margins, causing the fringes to be pushed inside, which may be visually distracting. This option keeps the fringes at the window’s edges. Unset it if you prefer to have the fringes close to the text. 79 | 80 | 81 | ### Fullscreen Effect ### 82 | 83 | Effect to apply when `writeroom-mode` activates fullscreen. Can be `fullboth`, which uses the entire screen (i.e., window decorations are disabled and the window manager’s panel or task bar is covered by the Emacs frame) or `maximized`, in which case the Emacs frame is maximised but keeps its window decorations and does not cover the panel. 84 | 85 | 86 | ### Global Effects ### 87 | 88 | List of global effects: 89 | 90 | - fullscreen 91 | - transparency 92 | - scroll bar 93 | - menu bar 94 | - tool bar 95 | - bottom window divider 96 | - border (add a border around the text area; disabled by default) 97 | - sticky (display the window on all virtual workspaces; disabled by default) 98 | 99 | Each option can be enabled or disabled individually. 100 | 101 | 102 | ### Header Line ### 103 | 104 | The header line format to use. This option can be `nil` (the default), which disables the header line entirely, it can be `t`, which retains the header line, or it can be set to a customised format. Note that Emacs does not use the header line by default, so changing this option from the default only makes sense if you have a customised header line that you do not want to be displayed in `writeroom-mode` buffers. 105 | 106 | As an additional possibility, this option can be set to the symbol `mode-line`, in which case the standard mode line is shown in the header line. 107 | 108 | 109 | ### Maximize Window ### 110 | 111 | Maximise the current window in its frame, i.e., delete all other windows. 112 | 113 | 114 | ### Writeroom-mode Disable Hook ### 115 | 116 | Hook run when `writeroom-mode` is disabled. This hook can be used to disable effects that are enabled in `writeroom-mode-enable-hook` (see below). 117 | 118 | 119 | ### Writeroom-mode Enable Hook ### 120 | 121 | Hook run when `writeroom-mode` is enabled. This hook is run just before `writeroom-mode-hook` is run. Unlike `writeroom-mode-hook`, it is not run when `writeroom-mode` is disabled. 122 | 123 | Note, however, that if you have a minor mode that you want activated and deactivated along with `writeroom-mode` (e.g., `variable-pitch-mode`), it is usually more convenient to simply add it to the option `writeroom-local-effects` (see below). 124 | 125 | 126 | ### Left Shift ### 127 | 128 | The number of columns by which the text area is shifted to the left (if positive) or right (if negative). This can be a number or a list of functions that each return a number, which are then summed. By default, the text area is shifted by the width of the line number column. 129 | 130 | 131 | ### Local Effects ### 132 | 133 | A list of functions that enable buffer-local effects. These functions are called with the argument `1` when `writeroom-mode` is enabled and with the argument `-1` when it is disabled. 134 | 135 | You can add minor modes to this option that you want activated together with `writeroom-mode` but also deactivated again when you deactivate `writeroom-mode`. You can, of course also add your own functions to this option, provided they take the arguments `1` and `-1`. 136 | 137 | 138 | ### Mode Line ### 139 | 140 | The mode line format to use. This option can be `nil` (the default), which disables the mode line altogether, it can be `t`, which retains the mode line, or it can be set to a customised format to only show some information. If the latter option is chosen, the mode line shows only the file name and the file modification status, but the format can be customised. See the documentation for the variable `mode-line-format` for details. If you set this option, it may be more visually pleasing to set the option Bottom Divider Width to 0. 141 | 142 | 143 | ### Mode Line Toggle Position ### 144 | 145 | If you disable or customise the mode line, you may sometimes want to see the entire mode line. `writeroom-mode` provides the function `writeroom-toggle-mode-line` (see below) to do this. You can specify where you want to make the mode line visible when using this function: in the mode line itself, or in the header line. 146 | 147 | Note that the default value of this option is to display the mode line in the header line, because for some reason that is more reliable. (Toggling the mode line multiple times in a row does not always work very well.) 148 | 149 | 150 | ### Restore Window Config ### 151 | 152 | Restore the window configuration that existed before `writeroom-mode` was activated. This is primarily useful if you use `writeroom-mode` in only a single buffer, since the window configuration that is restored is the one that existed at the moment when `writeroom-mode` is called for the first time. Disabled by default. 153 | 154 | 155 | ### Width ### 156 | 157 | Width of the text area. Can be specified as an absolute value (number of characters) or as a fraction of the total window width (in which case it should be a number between 0 and 1). 158 | 159 | 160 | ## Changing the width interactively ## 161 | 162 | The width of the text area in the current buffer can be changed interactively with the commands `writeroom-increase-width` and `writeroom-decrease-width`, which increase and decrease the text width by 2 characters. There is also a more general command `writeroom-adjust-width`, which adjusts the width of the text area by the amount passed as prefix argument. That is, calling it with `M-5 M-x writeroom-adjust-width` increases the text width by 5 characters. Calling `writeroom-adjust-width` without prefix argument resets the width to the default value. 163 | 164 | These commands are not bound to any keys, but you can bind them in the following manner (the actual keys are just examples, of course; choose any keys you like): 165 | 166 | ```lisp 167 | (with-eval-after-load 'writeroom-mode 168 | (define-key writeroom-mode-map (kbd "C-M-<") #'writeroom-decrease-width) 169 | (define-key writeroom-mode-map (kbd "C-M->") #'writeroom-increase-width) 170 | (define-key writeroom-mode-map (kbd "C-M-=") #'writeroom-adjust-width)) 171 | ``` 172 | 173 | 174 | ## Text size adjustments ## 175 | 176 | Text size adjustments are taken into account in calculating the margins, which means that if the text size is increased, the margins are decreased, so that the number of characters on the line remains more or less the same. Since it is not possible to detect interactive text size adjustments (e.g., with `text-size-adjust`), the adjustments of the margins cannot be made automatically. You need to force a redisplay, e.g., with the command `redraw-display`. 177 | 178 | Alternatively, you can advise the command you use for adjusting the text size (most likely `text-size-adjust`): 179 | 180 | (advice-add 'text-scale-adjust :after 181 | #'visual-fill-column-adjust) 182 | 183 | 184 | ## Displaying the mode line ## 185 | 186 | By default, `writeroom-mode` disables the mode line. If you occasionally need to see the full mode line, you can use the command `writeroom-toggle-mode-line`, which makes the mode line visible. Calling it again hides the mode line. This command is bound to `s-?` (`s` is the super key, i.e., the Windows key on PCs, the ⌘ key on Macs), but it can be rebound by putting something like the following in your `init.el`: 187 | 188 | ```lisp 189 | (with-eval-after-load 'writeroom-mode 190 | (define-key writeroom-mode-map (kbd "s-?") nil) 191 | (define-key writeroom-mode-map (kbd "") #’writeroom-toggle-mode-line)) 192 | ``` 193 | 194 | The first `define-key` disables the binding for `s-?`. Substitute your preferred key binding in the second line to bind `writeroom-toggle-mode-line` to it. 195 | 196 | 197 | ## Adding global effects ## 198 | 199 | It is possible to add your own global effects to `writeroom-mode`. If there is a global minor mode that you want turned on when `writeroom-mode` is activated for the first time, you can simply add it to the user option `writeroom-global-effects` by checking the box "Custom effects", clicking the `[INS]` button and adding the function to the list. 200 | 201 | Alternatively, you can also write your own function. This function should take one argument and enable the effect if the argument is `1` and disable it if the argument is `-1`. To give an example, if you want to activate a minimalist colour theme in `writeroom-mode`, you can write the following function: 202 | 203 | ```lisp 204 | (defun my-writeroom-theme (arg) 205 | (cond 206 | ((= arg 1) 207 | (enable-theme 'minimalist-dark)) 208 | ((= arg -1) 209 | (disable-theme 'minimalist-dark)))) 210 | ``` 211 | 212 | If your function affects the frame, you should make sure that it only affects the `writeroom-mode` frame by passing the variable `writeroom--frame` to all frame-changing functions. If your frame effect involves changing the value of a frame parameter, you may be able to use the macro `define-writeroom-global-effect`; see its doc string for details. 213 | 214 | In principle, it is not a good idea to define a custom global effect function as a toggle, but if you are sure you'll only ever use a single frame, it should be safe enough. For example, sometimes setting the `fullscreen` frame parameter does not work. In this case, if you're on Linux, you could send an X client message directly: 215 | 216 | ```lisp 217 | (defun my-toggle-fullscreen (_) 218 | (x-send-client-message nil 0 nil "_NET_WM_STATE" 32 219 | '(2 "_NET_WM_STATE_FULLSCREEN" 0))) 220 | ``` 221 | 222 | 223 | ## Other similar modes ## 224 | 225 | There are two other modes that I know of that also implement a distraction-free writing environment: [Darkroom](https://github.com/joaotavora/darkroom) and [Olivetti](https://github.com/rnkn/olivetti). Both are narrower in scope than `writeroom-mode`. 226 | 227 | In particular, both Darkroom and Olivetti only affect the buffer (or more precisely, its window), not the frame. They centre the text by adding window margins, and optionally resize the text and hide the mode line. They do not make Emacs fullscreen and do not remove the menu and tool bars, the scroll bar or the window decorations. This is a conscious choice (see, e.g., [this pull request](https://github.com/joaotavora/darkroom/pull/2) and [this issue](https://github.com/rnkn/olivetti/issues/6)), motivated by the fact that affecting the frame in this way may lead to problems when using multiple Emacs frames. 228 | 229 | It is true that changing the appearance of the current frame (the global effects, as `writeroom-mode` calls them) is risky if you use multiple frames. `writeroom-mode` applies its global effects to the frame that is current when it is first activated and tries to make sure that *only* this frame is ever affected. Therefore, it should be safe to use `writeroom-mode`, even if you use multiple frames. (If you do run into issues, however, I would welcome a bug report.) Alternatively, you can turn off all global effects and use `writeroom-mode` in much the same way as Darkroom or Olivetti. 230 | 231 | Another difference with Darkroom and Olivetti is that `writeroom-mode` tries to be as customisable as possible. It has a larger number of customisation options than either of the other modes and also provides a way to add custom global effects. This may or may not be what you need, of course. 232 | -------------------------------------------------------------------------------- /pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ ! "$(git status --porcelain README.md)" == 'M README.md' ] ; then 4 | exit 0 # everything's fine 5 | fi 6 | 7 | # otherwise generate info file and git-add it. 8 | 9 | git stash -q --keep-index 10 | 11 | pandoc --read=markdown \ 12 | --write=texinfo \ 13 | --output=/home/joost/src/writeroom-mode/writeroom-mode.texi \ 14 | --include-before-body=/home/joost/src/writeroom-mode/texi-before-body \ 15 | --standalone \ 16 | ./README.md 17 | 18 | RESULT=$? 19 | 20 | [ $RESULT == 0 ] && makeinfo ./writeroom-mode.texi && git add ./writeroom-mode.info 21 | 22 | git stash pop -q 23 | 24 | [ $RESULT -ne 0 ] && exit 1 25 | 26 | exit 0 27 | -------------------------------------------------------------------------------- /test/test-helper.el: -------------------------------------------------------------------------------- 1 | ;;; test-helper.el --- Helpers for writeroom-mode-test.el 2 | 3 | ;;; test-helper.el ends here 4 | -------------------------------------------------------------------------------- /test/writeroom-mode-test.el: -------------------------------------------------------------------------------- 1 | ;;; writeroom-mode-test.el --- Tests for writeroom-mode 2 | 3 | (require 'writeroom-mode) 4 | 5 | (ert-deftest writeroom--match-major-mode-test () 6 | ;; Match major mode symbol. 7 | (should (eq (let ((major-mode 'mock-mode)) 8 | (writeroom--match-major-mode '(text-mode mock-mode))) 9 | t)) 10 | ;; Match derived mode. 11 | (should (eq (let ((major-mode 'mock-mode)) 12 | (put 'mock-mode 'derived-mode-parent 'text-mode) 13 | (writeroom--match-major-mode '(text-mode) t)) 14 | t)) 15 | ;; Fail when major mode not present. 16 | (should (eq (let ((major-mode 'mock-mode)) 17 | (writeroom--match-major-mode '(text-mode))) 18 | nil)) 19 | ;; Match partial mode name if a string. 20 | (should (eq (let ((major-mode 'emacs-lisp-mode)) 21 | (writeroom--match-major-mode '(text-mode "lisp-mode"))) 22 | t)) 23 | ;; Fail when partial mode name is not a string. 24 | (should (eq (let ((major-mode 'emacs-lisp-mode)) 25 | (writeroom--match-major-mode '(text-mode lisp-mode))) 26 | nil))) 27 | 28 | ;;; writeroom-mode-test.el ends here 29 | -------------------------------------------------------------------------------- /texi-before-body: -------------------------------------------------------------------------------- 1 | 2 | @dircategory Emacs 3 | @direntry 4 | * Writeroom Mode: (writeroom-mode). Distraction-free writing. 5 | @end direntry 6 | -------------------------------------------------------------------------------- /writeroom-mode.el: -------------------------------------------------------------------------------- 1 | ;;; writeroom-mode.el --- Minor mode for distraction-free writing -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (c) 2012-2025 Joost Kremers 4 | 5 | ;; Author: Joost Kremers 6 | ;; Maintainer: Joost Kremers 7 | ;; Created: 11 July 2012 8 | ;; Package-Requires: ((emacs "25.1") (visual-fill-column "2.2")) 9 | ;; Version: 3.12 10 | ;; Keywords: text 11 | ;; URL: https://github.com/joostkremers/writeroom-mode 12 | 13 | ;; Redistribution and use in source and binary forms, with or without 14 | ;; modification, are permitted provided that the following conditions 15 | ;; are met: 16 | ;; 17 | ;; 1. Redistributions of source code must retain the above copyright 18 | ;; notice, this list of conditions and the following disclaimer. 19 | ;; 2. Redistributions in binary form must reproduce the above copyright 20 | ;; notice, this list of conditions and the following disclaimer in the 21 | ;; documentation and/or other materials provided with the distribution. 22 | ;; 3. The name of the author may not be used to endorse or promote products 23 | ;; derived from this software without specific prior written permission. 24 | ;; 25 | ;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26 | ;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27 | ;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 | ;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29 | ;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30 | ;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE, 31 | ;; DATA, OR PROFITS ; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 | ;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 | ;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 | ;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | 36 | ;;; Commentary: 37 | 38 | ;; writeroom-mode is a minor mode for Emacs that implements a 39 | ;; distraction-free writing mode similar to the famous Writeroom editor for 40 | ;; OS X. writeroom-mode is meant for GNU Emacs 25 and isn't tested on older 41 | ;; versions. 42 | ;; 43 | ;; See the README or info manual for usage instructions. 44 | ;; 45 | ;;; Code: 46 | 47 | (require 'visual-fill-column) 48 | 49 | (defvar writeroom--frame nil 50 | "The frame in which `writeroom-mode' is activated. 51 | The global effects only apply to this frame.") 52 | 53 | (defvar writeroom--buffers nil 54 | "List of buffers in which `writeroom-mode' is activated.") 55 | 56 | (defvar writeroom--local-variables '(mode-line-format 57 | header-line-format 58 | line-spacing) 59 | "Local variables whose values are saved when `writeroom-mode' is activated.") 60 | 61 | (defvar writeroom--saved-data nil 62 | "Buffer-local data to be stored when `writeroom-mode' is activated. 63 | These settings are restored when `writeroom-mode' is 64 | deactivated.") 65 | (make-variable-buffer-local 'writeroom--saved-data) 66 | 67 | (defvar writeroom--saved-visual-fill-column nil 68 | "Status of `visual-fill-column-mode' before activating `writeroom-mode'.") 69 | (make-variable-buffer-local 'writeroom--saved-visual-fill-column) 70 | 71 | (defvar writeroom--saved-window-config nil 72 | "Window configuration active before `writeroom-mode' is activated.") 73 | 74 | (defgroup writeroom nil "Minor mode for distraction-free writing." 75 | :group 'text 76 | :prefix "writeroom-") 77 | 78 | (defcustom writeroom-width 80 79 | "Width of the writeroom writing area. 80 | This can be specified as an absolute width (the number of 81 | characters in a line), or as a fraction of the total window 82 | width, in the latter it should be a number between 0 and 1." 83 | :group 'writeroom 84 | :type '(choice (integer :tag "Absolute width:") 85 | (float :tag "Relative width:" :value 0.5))) 86 | 87 | (defun writeroom-full-line-number-width () 88 | "Return the line number width including padding. 89 | `line-number-display-width' does not include the two spaces used 90 | for padding the line number display." 91 | (if display-line-numbers 92 | (+ 2 (line-number-display-width)) 93 | 0)) 94 | 95 | (defcustom writeroom-added-width-left (if (>= emacs-major-version 26) 96 | #'writeroom-full-line-number-width 97 | 0) 98 | "Number of columns to add to the text area on the left. 99 | This can be a number or a function which should return a number." 100 | :group 'writeroom 101 | :type '(choice (const :tag "Do not add extra width" 0) 102 | (integer :tag "Fixed extra width") 103 | (function :tag "Function to calculate extra width"))) 104 | 105 | (defcustom writeroom-mode-line nil 106 | "The mode line format to use with `writeroom-mode'. 107 | By default, this option is set to nil, which disables the mode 108 | line when `writeroom-mode' is activated. By setting this option 109 | to t, the standard mode line is retained. Alternatively, it is 110 | possible to specify a special mode line for `writeroom-mode' 111 | buffers. If this option is chosen, the default is to only show 112 | the buffer's modification status and the buffer name, but the 113 | format can be customized. See the documentation for the variable 114 | `mode-line-format' for further information. Note that if you set 115 | this option, it may be more visually pleasing to set 116 | `writeroom-bottom-divider-width' to 0." 117 | :group 'writeroom 118 | :type '(choice (const :tag "Disable the mode line" nil) 119 | (const :tag "Use standard mode line" t) 120 | (sexp :tag "Customize mode line" 121 | :value (" " mode-line-modified " " mode-line-buffer-identification)))) 122 | 123 | (defcustom writeroom-header-line nil 124 | "The header line used with `writeroom-mode'. 125 | Possible values are nil (the default), which disables the header 126 | line; t, which retains the standard header line; the symbol 127 | `mode-line', which means to display the standard mode line in the 128 | header line (this value makes most sense when 129 | `writeroom-mode-line' is set to nil); or a sexp, which should be 130 | a valid mode line construct." 131 | :group 'writeroom 132 | :type '(choice (const :tag "Do not show the header line" nil) 133 | (const :tag "Use standard header line" t) 134 | (const :tag "Show standard mode line in header line" mode-line) 135 | (sexp :tag "Customize header line" 136 | :value nil))) 137 | 138 | (defcustom writeroom-mode-line-toggle-position 'header-line-format 139 | "Position to temporarily show the mode line. 140 | When the mode line is disabled, the function 141 | `writeroom-toggle-mode-line' makes the mode line visible. This 142 | option determines whether it is shown as the mode line or as the 143 | header line." 144 | :group 'writeroom 145 | :type '(choice (const :tag "Use the mode line" mode-line-format) 146 | (const :tag "Use the header line" header-line-format))) 147 | 148 | (defcustom writeroom-bottom-divider-width 1 149 | "Width of the bottom window divider in pixels." 150 | :group 'writeroom 151 | :type '(integer :tag "Width")) 152 | 153 | (make-obsolete-variable 'writeroom-disable-fringe 154 | "The variable `writeroom-disable-fringe' is no longer used." 155 | "`writeroom-mode' version 2.9") 156 | 157 | (defcustom writeroom-maximize-window t 158 | "Whether to maximize the current window in its frame. 159 | When set to t, `writeroom-mode' deletes all other windows in 160 | the current frame." 161 | :group 'writeroom 162 | :type '(choice (const :tag "Maximize window" t) 163 | (const :tag "Do not maximize window" nil))) 164 | 165 | (defcustom writeroom-fullscreen-effect 'fullboth 166 | "Effect applied when enabling fullscreen. 167 | The value can be `fullboth', in which case fullscreen is 168 | activated, or `maximized', in which case the relevant frame is 169 | maximized but window decorations are still available." 170 | :group 'writeroom 171 | :type '(choice (const :tag "Fullscreen" fullboth) 172 | (const :tag "Maximized" maximized))) 173 | 174 | (defcustom writeroom-border-width 30 175 | "Width in pixels of the border. 176 | To use this option, select the option \"Add border\" in `Global 177 | Effects'. This adds a border around the text area." 178 | :group 'writeroom 179 | :type '(integer :tag "Border width")) 180 | 181 | (defcustom writeroom-fringes-outside-margins t 182 | "If set, place the fringes outside the margins." 183 | :group 'writeroom 184 | :type '(choice (const :tag "Place fringes outside margins" t) 185 | (const :tag "Place fringes inside margins" nil))) 186 | 187 | (defcustom writeroom-major-modes '(text-mode) 188 | "List of major modes in which writeroom-mode is activated. 189 | The command `global-writeroom-mode' activates `writeroom-mode' in 190 | every buffer that has one of the major modes listed in this 191 | option. Modes can be specified as symbols or as regular 192 | expressions. If a buffer has one of the specified major modes or 193 | if its major mode name matches one of the regular expressions, 194 | `writeroom-mode' is activated." 195 | :group 'writeroom 196 | :type '(repeat (choice (symbol :tag "Major mode") 197 | (string :tag "Regular expression")))) 198 | 199 | (defcustom writeroom-use-derived-modes t 200 | "Activate `writeroom-mode' in derived modes as well.'. 201 | If this option is set, the command `global-writeroom-mode' 202 | activates `writeroom-mode' in modes that are derived from those 203 | listed in `writeroom-major-modes'. Note that this option applies 204 | only to symbols in `writeroom-major-modes'. Regular expressions 205 | are ignored." 206 | :group 'writeroom 207 | :type '(choice (const :tag "Use derived modes" t) 208 | (const :tag "Do not use derived modes" nil))) 209 | 210 | (defcustom writeroom-major-modes-exceptions nil 211 | "List of major modes in which `writeroom-mode' should not be activated. 212 | This option lists exceptions to `writeroom-major-modes'. Modes 213 | can be specified as symbols or as regular expressions." 214 | :group 'writeroom 215 | :type '(repeat (choice (symbol :tag "Major mode exception") 216 | (string :tag "Regular expression")))) 217 | 218 | (defcustom writeroom-restore-window-config nil 219 | "If set, restore window configuration after disabling `writeroom-mode'. 220 | Setting this option makes sense primarily if `writeroom-mode' is 221 | used in one buffer only. The window configuration that is stored 222 | is the one that exists when `writeroom-mode' is first called, and 223 | it is restored when `writeroom-mode' is deactivated in the last 224 | buffer." 225 | :group 'writeroom 226 | :type '(choice (const :tag "Do not restore window configuration" nil) 227 | (const :tag "Restore window configuration" t))) 228 | 229 | (defcustom writeroom-extra-line-spacing nil 230 | "Additional line spacing for `writeroom-mode`." 231 | :group 'writeroom 232 | :type '(choice (const :tag "Do not add extra line spacing" :value nil) 233 | (integer :tag "Absolute height" :value 5) 234 | (float :tag "Relative height" :value 0.8))) 235 | 236 | (defcustom writeroom-mode-enable-hook nil 237 | "Hook run when `writeroom-mode' is enabled. 238 | This hook is run after all `writeroom-mode'-specific effects have 239 | been enabled, but before `writeroom-mode-hook' itself is run. It 240 | can be used for enabling effects that cannot be enabled in 241 | `writeroom-mode-hook'." 242 | :group 'writeroom 243 | :type '(repeat function)) 244 | 245 | (defcustom writeroom-mode-disable-hook nil 246 | "Hook run when `writeroom-mode' is disabled. 247 | This hook is run after all `writeroom-mode'-specific effects have 248 | been disabled and the buffer state before enabling 249 | `writeroom-mode' has been restored. It can be used for disabling 250 | effects that were enabled in `writeroom-mode-enable-hook'." 251 | :group 'writeroom 252 | :type '(repeat function)) 253 | 254 | (define-obsolete-variable-alias 'writeroom-global-functions 'writeroom-global-effects "`writeroom-mode' version 2.0") 255 | 256 | (defcustom writeroom-global-effects '(writeroom-set-fullscreen 257 | writeroom-set-alpha 258 | writeroom-set-menu-bar-lines 259 | writeroom-set-tool-bar-lines 260 | writeroom-set-vertical-scroll-bars 261 | writeroom-set-bottom-divider-width) 262 | "List of global effects for `writeroom-mode'. 263 | These effects are enabled when `writeroom-mode' is activated in 264 | the first buffer and disabled when it is deactivated in the last 265 | buffer." 266 | :group 'writeroom 267 | :type '(set (const :tag "Fullscreen" writeroom-set-fullscreen) 268 | (const :tag "Disable transparency" writeroom-set-alpha) 269 | (const :tag "Disable menu bar" writeroom-set-menu-bar-lines) 270 | (const :tag "Disable tool bar" writeroom-set-tool-bar-lines) 271 | (const :tag "Disable scroll bar" writeroom-set-vertical-scroll-bars) 272 | (const :tag "Enable bottom window divider" writeroom-set-bottom-divider-width) 273 | (const :tag "Add border" writeroom-set-internal-border-width) 274 | (const :tag "Display frame on all workspaces" writeroom-set-sticky) 275 | (repeat :inline t :tag "Custom effects" function))) 276 | 277 | (defmacro define-writeroom-global-effect (fp value) 278 | "Define a global effect for `writeroom-mode'. 279 | The effect is activated by setting frame parameter FP to VALUE. 280 | FP should be an unquoted symbol, the name of a frame parameter; 281 | VALUE must be quoted (unless it is a string or a number, of 282 | course). It can also be an unquoted symbol, in which case it 283 | should be the name of a global variable whose value is then 284 | assigned to FP. 285 | 286 | This macro defines a function `writeroom-set-' that takes one 287 | argument and activates the effect if this argument is 1 and 288 | deactivates it if it is -1. When the effect is activated, the 289 | original value of frame parameter FP is stored in a frame 290 | parameter `writeroom-', so that it can be restored when the 291 | effect is deactivated." 292 | (declare (indent defun)) 293 | (let ((wfp (intern (format "writeroom-%s" fp)))) 294 | `(fset (quote ,(intern (format "writeroom-set-%s" fp))) 295 | (lambda (&optional arg) 296 | (when (frame-live-p writeroom--frame) 297 | (cond 298 | ((= arg 1) ; activate 299 | (set-frame-parameter writeroom--frame (quote ,wfp) (frame-parameter writeroom--frame (quote ,fp))) 300 | (set-frame-parameter writeroom--frame (quote ,fp) ,value)) 301 | ((= arg -1) ; deactivate 302 | (set-frame-parameter writeroom--frame (quote ,fp) (frame-parameter writeroom--frame (quote ,wfp))) 303 | (set-frame-parameter writeroom--frame (quote ,wfp) nil)))))))) 304 | 305 | (define-writeroom-global-effect fullscreen writeroom-fullscreen-effect) 306 | (define-writeroom-global-effect alpha '(100 100)) 307 | (define-writeroom-global-effect vertical-scroll-bars nil) 308 | (define-writeroom-global-effect menu-bar-lines 0) 309 | (define-writeroom-global-effect tool-bar-lines 0) 310 | (define-writeroom-global-effect internal-border-width writeroom-border-width) 311 | (define-writeroom-global-effect sticky t) 312 | (define-writeroom-global-effect bottom-divider-width writeroom-bottom-divider-width) 313 | 314 | (defcustom writeroom-local-effects nil 315 | "List of buffer-local effects for `writeroom-mode'. 316 | This should be a list of functions that activate or deactive some 317 | local effect. These functions are called with the argument \"1\" 318 | when `writeroom-mode' is enabled and with the argument \"-1\" 319 | when it is disabled. This means that you can add minor-mode 320 | symbols to this list and have them activated and deactivated 321 | together with `writeroom-mode'." 322 | :group 'writeroom 323 | :type '(repeat function)) 324 | 325 | (defun turn-on-writeroom-mode () 326 | "Turn on `writeroom-mode'. 327 | This function activates `writeroom-mode' in a buffer if that 328 | buffer's major mode matchs against one of `writeroom-major-modes'." 329 | (unless (writeroom--match-major-mode writeroom-major-modes-exceptions) 330 | (if (writeroom--match-major-mode writeroom-major-modes writeroom-use-derived-modes) 331 | (writeroom-mode 1)))) 332 | 333 | (defun writeroom--match-major-mode (modes &optional derived) 334 | "Match the current buffer's major mode against MODES. 335 | MODES a list of mode names (symbols) or regular expressions. 336 | Return t if the current major mode matches one of the elements of 337 | MODES, nil otherwise. Comparison is done with `eq` (for symbols 338 | in MODES) or with `string-match-p' (for strings in MODES). That 339 | is, if the major mode is e.g., `emacs-lisp-mode', it will not 340 | match the symbol `lisp-mode', but it will match the string 341 | \"lisp-mode\". 342 | 343 | If DERIVED is non-nil, also return t if the current buffer's 344 | major mode is a derived mode of one of the major mode symbols in 345 | MODES." 346 | (catch 'match 347 | (dolist (elem modes) 348 | (if (cond ((symbolp elem) 349 | (or (eq elem major-mode) 350 | (and derived (derived-mode-p elem)))) 351 | ((string-match-p elem (symbol-name major-mode)))) 352 | (throw 'match t))))) 353 | 354 | (defvar writeroom-mode-map 355 | (let ((map (make-sparse-keymap))) 356 | (define-key map (kbd "s-?") #'writeroom-toggle-mode-line) 357 | map) 358 | "Keymap for writeroom-mode.") 359 | 360 | ;;;###autoload 361 | (define-minor-mode writeroom-mode 362 | "Minor mode for distraction-free writing." 363 | :init-value nil :lighter nil :global nil 364 | (if writeroom-mode 365 | (writeroom--enable) 366 | (writeroom--disable))) 367 | 368 | ;;;###autoload 369 | (define-globalized-minor-mode global-writeroom-mode writeroom-mode turn-on-writeroom-mode 370 | :require 'writeroom-mode 371 | :group 'writeroom) 372 | 373 | (defun writeroom--kill-buffer-function () 374 | "Disable `writeroom-mode' before killing a buffer, if necessary. 375 | This function is for use in `kill-buffer-hook'. It checks whether 376 | `writeroom-mode' is enabled in the buffer to be killed and 377 | adjusts `writeroom--buffers' and the global effects accordingly." 378 | (when writeroom-mode 379 | (setq writeroom--buffers (delq (current-buffer) writeroom--buffers)) 380 | (when (not writeroom--buffers) 381 | (writeroom--set-global-effects -1) 382 | (setq writeroom--frame nil)))) 383 | 384 | (add-hook 'kill-buffer-hook #'writeroom--kill-buffer-function) 385 | 386 | (defun writeroom--set-global-effects (arg) 387 | "Activate or deactivate global effects. 388 | The effects are activated if ARG is 1, deactivated if it is -1." 389 | (mapc (lambda (fn) 390 | (funcall fn arg)) 391 | writeroom-global-effects)) 392 | 393 | (defun writeroom--calculate-width () 394 | "Calculate the width of the writing area." 395 | (if (floatp writeroom-width) 396 | (truncate (* (window-total-width) writeroom-width)) 397 | writeroom-width)) 398 | 399 | (defvar writeroom--mode-line-showing nil 400 | "Flag indicating whether the original mode line is displayed.") 401 | (make-variable-buffer-local 'writeroom--mode-line-showing) 402 | 403 | (defvar writeroom--orig-header-line nil 404 | "Original format of the header line. 405 | When the header line is used to temporarily display the mode 406 | line, its original format is saved here.") 407 | (make-variable-buffer-local 'writeroom--orig-header-line) 408 | 409 | (defun writeroom-toggle-mode-line () 410 | "Toggle display of the original mode." 411 | (interactive) 412 | (unless (or (eq writeroom-mode-line t) 413 | (eq writeroom-header-line 'mode-line)) ; This means the original mode-line is displayed already. 414 | (cond 415 | ((not writeroom--mode-line-showing) 416 | (setq writeroom--orig-header-line header-line-format) 417 | (set writeroom-mode-line-toggle-position (or (cdr (assq 'mode-line-format writeroom--saved-data)) 418 | (default-value 'mode-line-format))) 419 | (setq writeroom--mode-line-showing t)) 420 | (writeroom--mode-line-showing 421 | (if (eq writeroom-mode-line-toggle-position 'header-line-format) 422 | (setq header-line-format writeroom--orig-header-line) 423 | (setq mode-line-format writeroom-mode-line)) 424 | (setq writeroom--mode-line-showing nil))) 425 | (force-mode-line-update))) 426 | 427 | (defun writeroom-adjust-width (amount) 428 | "Adjust the width of the writing area on the fly by AMOUNT. 429 | A numeric prefix argument can be used to specify the adjustment. 430 | When called without a prefix, this will reset the width to the default value." 431 | (interactive "P") 432 | (if amount 433 | (setq visual-fill-column-width (max 1 (+ visual-fill-column-width amount))) 434 | (setq visual-fill-column-width (writeroom--calculate-width))) 435 | (visual-fill-column--adjust-window) 436 | (message "Writing area is now %d characters wide" visual-fill-column-width)) 437 | 438 | (defun writeroom-increase-width () 439 | "Increase the width of the writing area by 2 characters." 440 | (interactive) 441 | (writeroom-adjust-width 2)) 442 | 443 | (defun writeroom-decrease-width () 444 | "Decrease the width of the writing area by 2 characters." 445 | (interactive) 446 | (writeroom-adjust-width -2)) 447 | 448 | (defun writeroom--enable () 449 | "Set up writeroom-mode for the current buffer. 450 | Also run the functions in `writeroom-global-effects' if the 451 | current buffer is the first buffer in which `writeroom-mode' is 452 | activated." 453 | ;; Save buffer-local variables, if they have a buffer-local binding. 454 | (setq writeroom--saved-data (mapcar (lambda (sym) 455 | (if (local-variable-p sym) 456 | (cons sym (buffer-local-value sym (current-buffer))) 457 | sym)) 458 | writeroom--local-variables)) 459 | (setq writeroom--saved-visual-fill-column visual-fill-column-mode) 460 | 461 | ;; Activate global effects. 462 | (when (not writeroom--buffers) 463 | (setq writeroom--frame (selected-frame)) 464 | (writeroom--set-global-effects 1) 465 | (if writeroom-restore-window-config 466 | (setq writeroom--saved-window-config (current-window-configuration)))) 467 | 468 | (push (current-buffer) writeroom--buffers) 469 | 470 | (when writeroom-maximize-window 471 | (delete-other-windows)) 472 | 473 | (when writeroom-extra-line-spacing 474 | (setq line-spacing writeroom-extra-line-spacing)) 475 | 476 | (unless (eq writeroom-header-line t) ; If t, use standard header line. 477 | (if (eq writeroom-header-line 'mode-line) 478 | (setq header-line-format mode-line-format) 479 | (setq header-line-format writeroom-header-line))) 480 | 481 | (unless (eq writeroom-mode-line t) ; If t, use standard mode line. 482 | (setq mode-line-format writeroom-mode-line)) 483 | 484 | (setq visual-fill-column-width (writeroom--calculate-width) 485 | visual-fill-column-center-text t 486 | visual-fill-column-fringes-outside-margins writeroom-fringes-outside-margins 487 | visual-fill-column-extra-text-width (cons (cond 488 | ((numberp writeroom-added-width-left) 489 | writeroom-added-width-left) 490 | ((functionp writeroom-added-width-left) 491 | (funcall writeroom-added-width-left)) 492 | (t 0)) 493 | 0)) 494 | (visual-fill-column-mode 1) 495 | 496 | ;; Run hooks on enabling `writeroom-mode'. 497 | (run-hook-with-args 'writeroom-local-effects 1) 498 | (run-hooks 'writeroom-mode-enable-hook) 499 | 500 | ;; If the current buffer is displayed in some window, the windows' 501 | ;; margins and fringes must be adjusted. 502 | (mapc (lambda (w) 503 | (with-selected-window w 504 | (visual-fill-column--adjust-window))) 505 | (get-buffer-window-list (current-buffer) nil))) 506 | 507 | (defun writeroom--disable () 508 | "Reset the current buffer to its normal appearance. 509 | Also run the functions in `writeroom-global-effects' to undo 510 | their effects if `writeroom-mode' is deactivated in the last 511 | buffer in which it was active." 512 | ;; Disable visual-fill-column-mode. 513 | (visual-fill-column-mode -1) 514 | (kill-local-variable 'visual-fill-column-width) 515 | (kill-local-variable 'visual-fill-column-center-text) 516 | (kill-local-variable 'visual-fill-column-fringes-outside-margins) 517 | (kill-local-variable 'visual-fill-column-extra-text-width) 518 | 519 | ;; Restore global effects if necessary. 520 | (setq writeroom--buffers (delq (current-buffer) writeroom--buffers)) 521 | (when (not writeroom--buffers) 522 | (writeroom--set-global-effects -1) 523 | (setq writeroom--frame nil) 524 | (if writeroom-restore-window-config 525 | (set-window-configuration writeroom--saved-window-config))) 526 | 527 | ;; Restore local variables. 528 | (mapc (lambda (val) 529 | (if (symbolp val) 530 | (kill-local-variable val) 531 | (set (car val) (cdr val)))) 532 | writeroom--saved-data) 533 | 534 | ;; If the current buffer is displayed in some window, the windows' 535 | ;; margins and fringes must be adjusted. 536 | (mapc (lambda (w) 537 | (with-selected-window w 538 | (set-window-margins (selected-window) 0 0) 539 | (set-window-fringes (selected-window) nil))) 540 | (get-buffer-window-list (current-buffer) nil)) 541 | 542 | ;; Reenable `visual-fill-colummn-mode' with original settings if it was 543 | ;; active before activating `writeroom-mode'. 544 | (if writeroom--saved-visual-fill-column 545 | (visual-fill-column-mode 1)) 546 | 547 | ;; Run hook on disabling `writeroom-mode'. 548 | (run-hook-with-args 'writeroom-local-effects -1) 549 | (run-hooks 'writeroom-mode-disable-hook)) 550 | 551 | (provide 'writeroom-mode) 552 | 553 | ;;; writeroom-mode.el ends here 554 | -------------------------------------------------------------------------------- /writeroom-mode.info: -------------------------------------------------------------------------------- 1 | This is writeroom-mode.info, produced by makeinfo version 6.5 from 2 | writeroom-mode.texi. 3 | 4 | INFO-DIR-SECTION Emacs 5 | START-INFO-DIR-ENTRY 6 | * Writeroom Mode: (writeroom-mode). Distraction-free writing. 7 | END-INFO-DIR-ENTRY 8 | 9 |  10 | File: writeroom-mode.info, Node: Top, Next: Writeroom-mode, Up: (dir) 11 | 12 | Top 13 | *** 14 | 15 | * Menu: 16 | 17 | * Writeroom-mode:: 18 | 19 |  20 | File: writeroom-mode.info, Node: Writeroom-mode, Prev: Top, Up: Top 21 | 22 | 1 Writeroom-mode 23 | **************** 24 | 25 | ‘writeroom-mode’ is a minor mode for Emacs that implements a 26 | distraction-free writing mode similar to the famous Writeroom editor for 27 | OS X. ‘writeroom-mode’ is meant for GNU Emacs 24, lower versions are not 28 | actively supported. 29 | 30 | * Menu: 31 | 32 | * Installation:: 33 | * Usage:: 34 | * Multiple writeroom-mode buffers:: 35 | * Frame effects:: 36 | * Customisation:: 37 | * Changing the width interactively:: 38 | * Text size adjustments:: 39 | * Displaying the mode line:: 40 | * Adding global effects:: 41 | * Other similar modes:: 42 | 43 |  44 | File: writeroom-mode.info, Node: Installation, Next: Usage, Up: Writeroom-mode 45 | 46 | 1.1 Installation 47 | ================ 48 | 49 | ‘writeroom-mode’ can be installed through the package manager from Melpa 50 | (http://melpa.org/). If installing manually, make sure to also install 51 | its dependency ‘visual-fill-column’ 52 | (https://github.com/joostkremers/visual-fill-column). 53 | 54 |  55 | File: writeroom-mode.info, Node: Usage, Next: Multiple writeroom-mode buffers, Prev: Installation, Up: Writeroom-mode 56 | 57 | 1.2 Usage 58 | ========= 59 | 60 | ‘writeroom-mode’ can be activated in a buffer by calling ‘M-x 61 | writeroom-mode RET’. A screen shot can probably explain best what 62 | ‘writeroom-mode’ does. In the default configuration, after activating 63 | ‘writeroom-mode’, your screen looks like this (modulo the colour theme, 64 | of course): 65 | 66 | [image src="writeroom-mode.png" alt="screenshot"] 67 | 68 | screenshot 69 | 70 | By default, ‘writeroom-mode’ does the following things: 71 | 72 | • activate fullscreen 73 | • disable transparency 74 | • disable the menu bar 75 | • disable the tool bar 76 | • disable the scroll bar 77 | • enable a bottom window divider of 1 pixel 78 | • maximise the current window (i.e., delete all other windows in the 79 | frame) 80 | • place the fringes outside the margins 81 | • disable the mode line 82 | • add window margins to the current buffer so that the text is 80 83 | characters wide 84 | 85 | The last three effects are buffer-local. The other effects apply to the 86 | current frame. Because ‘writeroom-mode’ is a minor mode, this isn’t 87 | entirely on the up and up, since minor modes aren’t supposed to have 88 | such global effects. But ‘writeroom-mode’ is meant for distraction-free 89 | writing, so these effects do make sense. 90 | 91 | All these effects can be disabled or customised. In addition, there are 92 | several more options that are disabled by default but can be enabled in 93 | the *note customisation buffer: #customisation. 94 | 95 |  96 | File: writeroom-mode.info, Node: Multiple writeroom-mode buffers, Next: Frame effects, Prev: Usage, Up: Writeroom-mode 97 | 98 | 1.3 Multiple writeroom-mode buffers 99 | =================================== 100 | 101 | It is possible to activate ‘writeroom-mode’ in more than one buffer. 102 | The global effects are of course activated only once and they remain 103 | active until ‘writeroom-mode’ is deactivated in _all_ buffers. 104 | Alternatively, if you wish to use ‘writeroom-mode’ in all buffers that 105 | have a particular major mode (e.g., ‘text-mode’, ‘markdown-mode’), you 106 | can use the global minor mode ‘global-writeroom-mode’. This function 107 | enables the global effects and activates the buffer-local effects in all 108 | (current and future) buffers that have a major mode listed in the user 109 | option ‘writeroom-major-modes’ (by default only ‘text-mode’). 110 | 111 | When ‘global-writeroom-mode’ is active, the function ‘writeroom-mode’ 112 | can still be called to enable or disable ‘writeroom-mode’ in individual 113 | buffers (regardless of their major mode, of course). Calling 114 | ‘global-writeroom-mode’ again disables ‘writeroom-mode’ in all buffers 115 | in which it is active, also those in which it was activated manually. 116 | 117 |  118 | File: writeroom-mode.info, Node: Frame effects, Next: Customisation, Prev: Multiple writeroom-mode buffers, Up: Writeroom-mode 119 | 120 | 1.4 Frame effects 121 | ================= 122 | 123 | Most of the global effects that ‘writeroom-mode’ enables are handled by 124 | setting specific frame parameters. This means that they apply to the 125 | current frame. If you switch to another frame and display a 126 | ‘writeroom-mode’ buffer, only the buffer-local effects will be visible. 127 | 128 | ‘writeroom-mode’ tries to make sure that it only affects one frame, and 129 | that it restores that particular frame when it is deactivated in the 130 | last buffer. This means it should be safe to activate ‘writeroom-mode’ 131 | in one frame and deactivate it in another. Killing the ‘writeroom-mode’ 132 | frame should also be safe. 133 | 134 | The affected frame is always restored to its original state, before 135 | ‘writeroom-mode’ was activated, even if you change any of the frame 136 | parameters manually while ‘writeroom-mode’ is active. 137 | 138 |  139 | File: writeroom-mode.info, Node: Customisation, Next: Changing the width interactively, Prev: Frame effects, Up: Writeroom-mode 140 | 141 | 1.5 Customisation 142 | ================= 143 | 144 | The customisation buffer for ‘writeroom-mode’ can be opened with ‘M-x 145 | customize-group RET writeroom RET’. It provides the options listed 146 | below. 147 | 148 | * Menu: 149 | 150 | * Added Width Left:: 151 | * Border Width:: 152 | * Bottom Divider Width:: 153 | * Extra Line Spacing:: 154 | * Fringes Outside Margins:: 155 | * Fullscreen Effect:: 156 | * Global Effects:: 157 | * Header Line:: 158 | * Maximize Window:: 159 | * Writeroom-mode Disable Hook:: 160 | * Writeroom-mode Enable Hook:: 161 | * Left Shift:: 162 | * Local Effects:: 163 | * Mode Line:: 164 | * Mode Line Toggle Position:: 165 | * Restore Window Config:: 166 | * Width:: 167 | 168 |  169 | File: writeroom-mode.info, Node: Added Width Left, Next: Border Width, Up: Customisation 170 | 171 | 1.5.1 Added Width Left 172 | ---------------------- 173 | 174 | Extra columns added to the left side of the text area. These columns 175 | are added after the text area is centred, so that the text area is 176 | essentially off-set to the left by the amount provided. This can be an 177 | integer or a function of no arguments that should return an integer. By 178 | default, this is used to accommodate line numbers if 179 | ‘display-line-numbers-mode’ is active, so that the actual text is still 180 | centred. 181 | 182 |  183 | File: writeroom-mode.info, Node: Border Width, Next: Bottom Divider Width, Prev: Added Width Left, Up: Customisation 184 | 185 | 1.5.2 Border Width 186 | ------------------ 187 | 188 | Width of the border around the text area. Disabled by default, see 189 | ‘writeroom-global-effects’ to enable the border. 190 | 191 |  192 | File: writeroom-mode.info, Node: Bottom Divider Width, Next: Extra Line Spacing, Prev: Border Width, Up: Customisation 193 | 194 | 1.5.3 Bottom Divider Width 195 | -------------------------- 196 | 197 | Width in pixels of the bottom window divider. Default value is 1. The 198 | bottom window divider helps in distinguishing the minibuffer from the 199 | text area, and also in distinguishing two windows split top-to-bottom. 200 | 201 |  202 | File: writeroom-mode.info, Node: Extra Line Spacing, Next: Fringes Outside Margins, Prev: Bottom Divider Width, Up: Customisation 203 | 204 | 1.5.4 Extra Line Spacing 205 | ------------------------ 206 | 207 | Increase the line spacing. Can be an absolute value (the number of 208 | pixels to add to the line) or a number relative to the default line 209 | height. Disabled by default. 210 | 211 |  212 | File: writeroom-mode.info, Node: Fringes Outside Margins, Next: Fullscreen Effect, Prev: Extra Line Spacing, Up: Customisation 213 | 214 | 1.5.5 Fringes Outside Margins 215 | ----------------------------- 216 | 217 | If set, place the fringes outside the margins. ‘writeroom-mode’ expands 218 | the window margins, causing the fringes to be pushed inside, which may 219 | be visually distracting. This option keeps the fringes at the window’s 220 | edges. Unset it if you prefer to have the fringes close to the text. 221 | 222 |  223 | File: writeroom-mode.info, Node: Fullscreen Effect, Next: Global Effects, Prev: Fringes Outside Margins, Up: Customisation 224 | 225 | 1.5.6 Fullscreen Effect 226 | ----------------------- 227 | 228 | Effect to apply when ‘writeroom-mode’ activates fullscreen. Can be 229 | ‘fullboth’, which uses the entire screen (i.e., window decorations are 230 | disabled and the window manager’s panel or task bar is covered by the 231 | Emacs frame) or ‘maximized’, in which case the Emacs frame is maximised 232 | but keeps its window decorations and does not cover the panel. 233 | 234 |  235 | File: writeroom-mode.info, Node: Global Effects, Next: Header Line, Prev: Fullscreen Effect, Up: Customisation 236 | 237 | 1.5.7 Global Effects 238 | -------------------- 239 | 240 | List of global effects: 241 | 242 | • fullscreen 243 | • transparency 244 | • scroll bar 245 | • menu bar 246 | • tool bar 247 | • bottom window divider 248 | • border (add a border around the text area; disabled by default) 249 | • sticky (display the window on all virtual workspaces; disabled by 250 | default) 251 | 252 | Each option can be enabled or disabled individually. 253 | 254 |  255 | File: writeroom-mode.info, Node: Header Line, Next: Maximize Window, Prev: Global Effects, Up: Customisation 256 | 257 | 1.5.8 Header Line 258 | ----------------- 259 | 260 | The header line format to use. This option can be ‘nil’ (the default), 261 | which disables the mode line entirely, it can be ‘t’, which retains the 262 | mode line, or it can be set to a customised format. Note that Emacs 263 | does not normally use the mode line, so changing this option from the 264 | default only makes sense if you have a customised header line that you 265 | do not want to be displayed in ‘writeroom-mode’ buffers. 266 | 267 | As an additional possibility, this option can be set to the symbol 268 | ‘mode-line’, in which case the standard mode line is shown in the header 269 | line. 270 | 271 |  272 | File: writeroom-mode.info, Node: Maximize Window, Next: Writeroom-mode Disable Hook, Prev: Header Line, Up: Customisation 273 | 274 | 1.5.9 Maximize Window 275 | --------------------- 276 | 277 | Maximise the current window in its frame, i.e., delete all other 278 | windows. 279 | 280 |  281 | File: writeroom-mode.info, Node: Writeroom-mode Disable Hook, Next: Writeroom-mode Enable Hook, Prev: Maximize Window, Up: Customisation 282 | 283 | 1.5.10 Writeroom-mode Disable Hook 284 | ---------------------------------- 285 | 286 | Hook run when ‘writeroom-mode’ is disabled. This hook can be used to 287 | disable effects that are enabled in ‘writeroom-mode-enable-hook’ (see 288 | below). 289 | 290 |  291 | File: writeroom-mode.info, Node: Writeroom-mode Enable Hook, Next: Left Shift, Prev: Writeroom-mode Disable Hook, Up: Customisation 292 | 293 | 1.5.11 Writeroom-mode Enable Hook 294 | --------------------------------- 295 | 296 | Hook run when ‘writeroom-mode’ is enabled. This hook is run just before 297 | ‘writeroom-mode-hook’ is run. Unlike ‘writeroom-mode-hook’, it is not 298 | run when ‘writeroom-mode’ is disabled. 299 | 300 | Note, however, that if you have a minor mode that you want activated and 301 | deactivated along with ‘writeroom-mode’ (e.g., ‘variable-pitch-mode’), 302 | it is usually more convenient to simply add it to the option 303 | ‘writeroom-local-effects’ (see below). 304 | 305 |  306 | File: writeroom-mode.info, Node: Left Shift, Next: Local Effects, Prev: Writeroom-mode Enable Hook, Up: Customisation 307 | 308 | 1.5.12 Left Shift 309 | ----------------- 310 | 311 | The number of columns by which the text area is shifted to the left (if 312 | positive) or right (if negative). This can be a number or a list of 313 | functions that each return a number, which are then summed. By default, 314 | the text area is shifted by the width of the line number column. 315 | 316 |  317 | File: writeroom-mode.info, Node: Local Effects, Next: Mode Line, Prev: Left Shift, Up: Customisation 318 | 319 | 1.5.13 Local Effects 320 | -------------------- 321 | 322 | A list of functions that enable buffer-local effects. These functions 323 | are called with the argument ‘1’ when ‘writeroom-mode’ is enabled and 324 | with the argument ‘-1’ when it is disabled. 325 | 326 | You can add minor modes to this option that you want activated together 327 | with ‘writeroom-mode’ but also deactivated again when you deactivate 328 | ‘writeroom-mode’. You can, of course also add your own functions to 329 | this option, provided they take the arguments ‘1’ and ‘-1’. 330 | 331 |  332 | File: writeroom-mode.info, Node: Mode Line, Next: Mode Line Toggle Position, Prev: Local Effects, Up: Customisation 333 | 334 | 1.5.14 Mode Line 335 | ---------------- 336 | 337 | The mode line format to use. This option can be ‘nil’ (the default), 338 | which disables the mode line altogether, it can be ‘t’, which retains 339 | the mode line, or it can be set to a customised format to only show some 340 | information. If the latter option is chosen, the mode line shows only 341 | the file name and the file modification status, but the format can be 342 | customised. See the documentation for the variable ‘mode-line-format’ 343 | for details. If you set this option, it may be more visually pleasing 344 | to set the option Bottom Divider Width to 0. 345 | 346 |  347 | File: writeroom-mode.info, Node: Mode Line Toggle Position, Next: Restore Window Config, Prev: Mode Line, Up: Customisation 348 | 349 | 1.5.15 Mode Line Toggle Position 350 | -------------------------------- 351 | 352 | If you disable or customise the mode line, you may sometimes want to see 353 | the entire mode line. ‘writeroom-mode’ provides the function 354 | ‘writeroom-toggle-mode-line’ (see below) to do this. You can specify 355 | where you want to make the mode line visible when using this function: 356 | in the mode line itself, or in the header line. 357 | 358 | Note that the default value of this option is to display the mode line 359 | in the header line, because for some reason that is more reliable. 360 | (Toggling the mode line multiple times in a row does not always work 361 | very well.) 362 | 363 |  364 | File: writeroom-mode.info, Node: Restore Window Config, Next: Width, Prev: Mode Line Toggle Position, Up: Customisation 365 | 366 | 1.5.16 Restore Window Config 367 | ---------------------------- 368 | 369 | Restore the window configuration that existed before ‘writeroom-mode’ 370 | was activated. This is primarily useful if you use ‘writeroom-mode’ in 371 | only a single buffer, since the window configuration that is restored is 372 | the one that existed at the moment when ‘writeroom-mode’ is called for 373 | the first time. Disabled by default. 374 | 375 |  376 | File: writeroom-mode.info, Node: Width, Prev: Restore Window Config, Up: Customisation 377 | 378 | 1.5.17 Width 379 | ------------ 380 | 381 | Width of the text area. Can be specified as an absolute value (number 382 | of characters) or as a fraction of the total window width (in which case 383 | it should be a number between 0 and 1). 384 | 385 |  386 | File: writeroom-mode.info, Node: Changing the width interactively, Next: Text size adjustments, Prev: Customisation, Up: Writeroom-mode 387 | 388 | 1.6 Changing the width interactively 389 | ==================================== 390 | 391 | The width of the text area in the current buffer can be changed 392 | interactively with the commands ‘writeroom-increase-width’ and 393 | ‘writeroom-decrease-width’, which increase and decrease the text width 394 | by 2 characters. There is also a more general command 395 | ‘writeroom-adjust-width’, which adjusts the width of the text area by 396 | the amount passed as prefix argument. That is, calling it with ‘M-5 M-x 397 | writeroom-adjust-width’ increases the text width by 5 characters. 398 | Calling ‘writeroom-adjust-width’ without prefix argument resets the 399 | width to the default value. 400 | 401 | These commands are not bound to any keys, but you can bind them in the 402 | following manner (the actual keys are just examples, of course; choose 403 | any keys you like): 404 | 405 | (with-eval-after-load 'writeroom-mode 406 | (define-key writeroom-mode-map (kbd "C-M-<") #'writeroom-decrease-width) 407 | (define-key writeroom-mode-map (kbd "C-M->") #'writeroom-increase-width) 408 | (define-key writeroom-mode-map (kbd "C-M-=") #'writeroom-adjust-width)) 409 | 410 |  411 | File: writeroom-mode.info, Node: Text size adjustments, Next: Displaying the mode line, Prev: Changing the width interactively, Up: Writeroom-mode 412 | 413 | 1.7 Text size adjustments 414 | ========================= 415 | 416 | Text size adjustments are taken into account in calculating the margins, 417 | which means that if the text size is increased, the margins are 418 | decreased, so that the number of characters on the line remains more or 419 | less the same. Since it is not possible to detect interactive text size 420 | adjustments (e.g., with ‘text-size-adjust’), the adjustments of the 421 | margins cannot be made automatically. You need to force a redisplay, 422 | e.g., with the command ‘redraw-display’. 423 | 424 | Alternatively, you can advise the command you use for adjusting the text 425 | size (most likely ‘text-size-adjust’): 426 | 427 | (advice-add 'text-scale-adjust :after 428 | #'visual-fill-column-adjust) 429 | 430 |  431 | File: writeroom-mode.info, Node: Displaying the mode line, Next: Adding global effects, Prev: Text size adjustments, Up: Writeroom-mode 432 | 433 | 1.8 Displaying the mode line 434 | ============================ 435 | 436 | By default, ‘writeroom-mode’ disables the mode line. If you 437 | occasionally need to see the full mode line, you can use the command 438 | ‘writeroom-toggle-mode-line’, which makes the mode line visible. 439 | Calling it again hides the mode line. This command is bound to ‘s-?’ 440 | (‘s’ is the super key, i.e., the Windows key on PCs, the ⌘ key on Macs), 441 | but it can be rebound by putting something like the following in your 442 | ‘init.el’: 443 | 444 | (with-eval-after-load 'writeroom-mode 445 | (define-key writeroom-mode-map (kbd "s-?") nil) 446 | (define-key writeroom-mode-map (kbd "") #’writeroom-toggle-mode-line)) 447 | 448 | The first ‘define-key’ disables the binding for ‘s-?’. Substitute your 449 | preferred key binding in the second line to bind 450 | ‘writeroom-toggle-mode-line’ to it. 451 | 452 |  453 | File: writeroom-mode.info, Node: Adding global effects, Next: Other similar modes, Prev: Displaying the mode line, Up: Writeroom-mode 454 | 455 | 1.9 Adding global effects 456 | ========================= 457 | 458 | It is possible to add your own global effects to ‘writeroom-mode’. If 459 | there is a global minor mode that you want turned on when 460 | ‘writeroom-mode’ is activated for the first time, you can simply add it 461 | to the user option ‘writeroom-global-effects’ by checking the box 462 | “Custom effects”, clicking the [INS] button and adding the function to 463 | the list. 464 | 465 | Alternatively, you can also write your own function. This function 466 | should take one argument and enable the effect if the argument is ‘1’ 467 | and disable it if the argument is ‘-1’. To give an example, if you want 468 | to activate a minimalist colour theme in ‘writeroom-mode’, you can write 469 | the following function: 470 | 471 | (defun my-writeroom-theme (arg) 472 | (cond 473 | ((= arg 1) 474 | (enable-theme 'minimalist-dark)) 475 | ((= arg -1) 476 | (disable-theme 'minimalist-dark)))) 477 | 478 | If your function affects the frame, you should make sure that it only 479 | affects the ‘writeroom-mode’ frame by passing the variable 480 | ‘writeroom--frame’ to all frame-changing functions. If your frame 481 | effect involves changing the value of a frame parameter, you may be able 482 | to use the macro ‘define-writeroom-global-effect’; see its doc string 483 | for details. 484 | 485 | In principle, it is not a good idea to define a custom global effect 486 | function as a toggle, but if you are sure you’ll only ever use a single 487 | frame, it should be safe enough. For example, sometimes setting the 488 | ‘fullscreen’ frame parameter does not work. In this case, if you’re on 489 | Linux, you could send an X client message directly: 490 | 491 | (defun my-toggle-fullscreen (_) 492 | (x-send-client-message nil 0 nil "_NET_WM_STATE" 32 493 | '(2 "_NET_WM_STATE_FULLSCREEN" 0))) 494 | 495 |  496 | File: writeroom-mode.info, Node: Other similar modes, Prev: Adding global effects, Up: Writeroom-mode 497 | 498 | 1.10 Other similar modes 499 | ======================== 500 | 501 | There are two other modes that I know of that also implement a 502 | distraction-free writing environment: Darkroom 503 | (https://github.com/joaotavora/darkroom) and Olivetti 504 | (https://github.com/rnkn/olivetti). Both are narrower in scope than 505 | ‘writeroom-mode’. 506 | 507 | In particular, both Darkroom and Olivetti only affect the buffer (or 508 | more precisely, its window), not the frame. They centre the text by 509 | adding window margins, and optionally resize the text and hide the mode 510 | line. They do not make Emacs fullscreen and do not remove the menu and 511 | tool bars, the scroll bar or the window decorations. This is a 512 | conscious choice (see, e.g., this pull request 513 | (https://github.com/joaotavora/darkroom/pull/2) and this issue 514 | (https://github.com/rnkn/olivetti/issues/6)), motivated by the fact that 515 | affecting the frame in this way may lead to problems when using multiple 516 | Emacs frames. 517 | 518 | It is true that changing the appearance of the current frame (the global 519 | effects, as ‘writeroom-mode’ calls them) is risky if you use multiple 520 | frames. ‘writeroom-mode’ applies its global effects to the frame that 521 | is current when it is first activated and tries to make sure that _only_ 522 | this frame is ever affected. Therefore, it should be safe to use 523 | ‘writeroom-mode’, even if you use multiple frames. (If you do run into 524 | issues, however, I would welcome a bug report.) Alternatively, you can 525 | turn off all global effects and use ‘writeroom-mode’ in much the same 526 | way as Darkroom or Olivetti. 527 | 528 | Another difference with Darkroom and Olivetti is that ‘writeroom-mode’ 529 | tries to be as customisable as possible. It has a larger number of 530 | customisation options than either of the other modes and also provides a 531 | way to add custom global effects. This may or may not be what you need, 532 | of course. 533 | 534 | 535 |  536 | Tag Table: 537 | Node: Top222 538 | Node: Writeroom-mode336 539 | Ref: #writeroom-mode445 540 | Node: Installation932 541 | Ref: #installation1052 542 | Node: Usage1296 543 | Ref: #usage1442 544 | Node: Multiple writeroom-mode buffers2846 545 | Ref: #multiple-writeroom-mode-buffers3045 546 | Node: Frame effects4063 547 | Ref: #frame-effects4234 548 | Node: Customisation5043 549 | Ref: #customisation5215 550 | Node: Added Width Left5746 551 | Ref: #added-width-left5888 552 | Node: Border Width6309 553 | Ref: #border-width6472 554 | Node: Bottom Divider Width6594 555 | Ref: #bottom-divider-width6775 556 | Node: Extra Line Spacing6989 557 | Ref: #extra-line-spacing7177 558 | Node: Fringes Outside Margins7344 559 | Ref: #fringes-outside-margins7539 560 | Node: Fullscreen Effect7832 561 | Ref: #fullscreen-effect8011 562 | Node: Global Effects8370 563 | Ref: #global-effects8531 564 | Node: Header Line8886 565 | Ref: #header-line9039 566 | Node: Maximize Window9614 567 | Ref: #maximize-window9788 568 | Node: Writeroom-mode Disable Hook9863 569 | Ref: #writeroom-mode-disable-hook10078 570 | Node: Writeroom-mode Enable Hook10235 571 | Ref: #writeroom-mode-enable-hook10443 572 | Node: Left Shift10900 573 | Ref: #left-shift11062 574 | Node: Local Effects11342 575 | Ref: #local-effects11493 576 | Node: Mode Line11978 577 | Ref: #mode-line12136 578 | Node: Mode Line Toggle Position12690 579 | Ref: #mode-line-toggle-position12888 580 | Node: Restore Window Config13441 581 | Ref: #restore-window-config13627 582 | Node: Width13964 583 | Ref: #width14084 584 | Node: Changing the width interactively14269 585 | Ref: #changing-the-width-interactively14487 586 | Node: Text size adjustments15492 587 | Ref: #text-size-adjustments15699 588 | Node: Displaying the mode line16356 589 | Ref: #displaying-the-mode-line16558 590 | Node: Adding global effects17344 591 | Ref: #adding-global-effects17538 592 | Node: Other similar modes19227 593 | Ref: #other-similar-modes19386 594 |  595 | End Tag Table 596 | 597 |  598 | Local Variables: 599 | coding: utf-8 600 | End: 601 | -------------------------------------------------------------------------------- /writeroom-mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joostkremers/writeroom-mode/cca2b4b3cfcfea1919e1870519d79ed1a69aa5e2/writeroom-mode.png --------------------------------------------------------------------------------