├── .gitignore ├── EmacsDocumentation-1.1beta.apk ├── LICENSE ├── README.md ├── documentation-generator.el ├── documentation-template.htmlt ├── full-feature-lister.el ├── htmlize.el └── sql-header.sqlt /.gitignore: -------------------------------------------------------------------------------- 1 | /documentation-generator.elc 2 | /full-feature-lister.elc 3 | /eod.db.zip 4 | /renew-tables.sql 5 | /symbols.db 6 | /symbols.db.bak 7 | /symbols.db.zip 8 | /htmlize.elc 9 | -------------------------------------------------------------------------------- /EmacsDocumentation-1.1beta.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Malabarba/emacs-online-documentation/5254e7bd035137998e5ff8eab1e00329f5538240/EmacsDocumentation-1.1beta.apk -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Artur 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | emacs-online-documentation 2 | ========================== 3 | 4 | A project meant to keep an updated online documentation of ALL emacs' built-in functions and variables. 5 | 6 | This documentation is available [here](http://malabarba.github.io/emacs-online-documentation/) (on the gh-page of this repo). 7 | -------------------------------------------------------------------------------- /documentation-generator.el: -------------------------------------------------------------------------------- 1 | ;;; documentation-generator.el --- Convert the documentation of all built-in functions and variables to html files. 2 | 3 | ;; Copyright (C) 2013 Artur Malabarba 4 | 5 | ;; Author: Artur Malabarba 6 | ;; URL: https://github.com/Bruce-Connor/emacs-online-documentation/ 7 | ;; Version: 0.5 8 | ;; Keywords: 9 | ;; ShortName: docgen 10 | ;; Separator: // 11 | 12 | ;;; Commentary: 13 | ;; 14 | ;; To run this, do: 15 | ;; 16 | ;; emacs --batch -l documentation-generator.el -f docgen//convert 17 | 18 | ;;; License: 19 | ;; 20 | ;; This file is NOT part of GNU Emacs. 21 | ;; 22 | ;; This program is free software; you can redistribute it and/or 23 | ;; modify it under the terms of the GNU General Public License 24 | ;; as published by the Free Software Foundation; either version 2 25 | ;; of the License, or (at your option) any later version. 26 | ;; 27 | ;; This program is distributed in the hope that it will be useful, 28 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 29 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 | ;; GNU General Public License for more details. 31 | ;; 32 | 33 | ;;; Change Log: 34 | ;; 0.5 - 20130822 - Improved removal of our own symbols 35 | ;; 0.5 - 20130822 - Implemented creation of an sqlite script 36 | ;; 0.5 - 20130819 - Use built-in url-hexify instead of concoting one. 37 | ;; 0.1 - 20130813 - Uploaded the file. 38 | ;; 0.1 - 20130811 - Created File. 39 | ;;; Code: 40 | 41 | (eval-and-compile (require 'cl-lib)) 42 | (load-file "./full-feature-lister.elc") 43 | (load-file "./htmlize.elc") 44 | 45 | (defconst docgen//version "0.5" "Version of the documentation-generator.el package.") 46 | (defconst docgen//version-int 3 "Version of the documentation-generator.el package, as an integer.") 47 | (defun docgen//bug-report () 48 | "Opens github issues page in a web browser. Please send me any bugs you find, and please include your emacs and dg versions." 49 | (interactive) 50 | (browse-url "https://github.com/Bruce-Connor/emacs-online-documentation/issues/new") 51 | (message "Your docgen//version is: %s, and your emacs version is: %s.\nPlease include this in your report!" 52 | docgen//version emacs-version)) 53 | 54 | (defcustom docgen//outdir (expand-file-name "~/Git-Projects/online-documentation-pages/") "" :type 'directory) 55 | (defcustom docgen//dir (expand-file-name "./") "" :type 'directory) 56 | 57 | (defcustom docgen//sql-script-file (expand-file-name "renew-tables.sql" docgen//outdir) "" :type 'file) 58 | (defconst docgen//sql-insert-string "\nINSERT INTO %s(Name, External) VALUES('%s', %s);") 59 | ;; (defconst docgen//sql-delete-string "\nDROP TABLE IF EXISTS %s;") 60 | ;; (defconst docgen//sql-create-string "\nCREATE VIRTUAL TABLE %s USING fts4(Name text UNIQUE NOT NULL, External integer);") 61 | 62 | (defvar docgen//description nil "The description function used.") 63 | (defvar docgen//count 0 "Used for reporting the progress of the conversion.") 64 | (defvar docgen//total 0 "Used for reporting the progress of the conversion.") 65 | (defcustom docgen//verbose t "Whether we should report the progress of the conversion." 66 | :type 'boolean) 67 | 68 | (defvar docgen//file-list-function nil) 69 | 70 | (defvar docgen//file-list-variable nil) 71 | 72 | (defvar docgen//file-list-face nil) 73 | 74 | (defun docgen//convert () 75 | "Do the whole thing. I'll comment this more when I have time." 76 | (interactive) 77 | (docgen//log "First, let's require all built-in features. So we know everything is defined.") 78 | (mapc 79 | (lambda (f) (condition-case nil 80 | (progn (message "%s" f) 81 | (require f nil t)) 82 | (error nil))) ;;no-error because some features are obsolete and throw errors. 83 | (docgen//full-feature-lister)) 84 | ;;;;;;;; 85 | (docgen//log "These lists will be used to create the functions.html and variables.html files") 86 | (setq docgen//file-list-variable nil 87 | docgen//file-list-function nil 88 | docgen//file-list-face nil) 89 | (docgen//log "Erase the sql-script, so we can make a new one.") 90 | ;; (when (file-readable-p docgen//sql-script-file) 91 | ;; (delete-file docgen//sql-script-file t)) 92 | (unless (file-writable-p docgen//sql-script-file) 93 | (error "Can't access sql script file %s" docgen//sql-script-file)) 94 | (with-temp-file docgen//sql-script-file 95 | (erase-buffer) 96 | (insert-file-contents-literally 97 | (expand-file-name "sql-header.sqlt" docgen//dir))) 98 | ;; (append-to-file (format docgen//sql-delete-string "Functions") nil docgen//sql-script-file) 99 | ;; (append-to-file (format docgen//sql-delete-string "Variables") nil docgen//sql-script-file) 100 | ;; (append-to-file (format docgen//sql-create-string "Functions") nil docgen//sql-script-file) 101 | ;; (append-to-file (format docgen//sql-create-string "Variables") nil docgen//sql-script-file) 102 | (setq docgen//documentation-template 103 | (with-temp-buffer 104 | (insert-file-contents-literally 105 | (file-relative-name "documentation-template.htmlt" docgen//dir)) 106 | (buffer-string))) 107 | (docgen//log "Generate the doc for functions") 108 | ;;;;;;;; 109 | (docgen//log "Create a doc file for each symbol.") 110 | (let ((docgen//sql-table-name "Functions") 111 | ;;This is to avoid artificial line breaks in the description. 112 | (fill-column 1000) 113 | ;;This tells `docgen//doc-to-html' what describing function to use. 114 | (docgen//description 'docgen//describe-function) 115 | (docgen//format "Fun/%s.html") 116 | (docgen//file-list 'docgen//file-list-function)) 117 | ;; This creates a file for each fbound symbol. 118 | (mapc 'docgen//symbol-to-file (docgen//function-list))) 119 | (docgen//log "Generate the doc for variables") 120 | (let ((docgen//sql-table-name "Variables") 121 | (docgen//description 'docgen//describe-variable) 122 | (docgen//format "Var/%s.html") 123 | (fill-column 1000) 124 | (docgen//file-list 'docgen//file-list-variable)) 125 | (mapc 'docgen//symbol-to-file (docgen//variable-list))) 126 | (docgen//log "Generate the doc for faces") 127 | (let ((docgen//sql-table-name "Faces") 128 | (docgen//description 'docgen//describe-face) 129 | (docgen//format "Face/%s.html") 130 | (fill-column 1000) 131 | (docgen//file-list 'docgen//file-list-face)) 132 | (mapc 'docgen//symbol-to-file (docgen//face-list))) 133 | ;; Create a file listing all of the docs. 134 | (docgen//log "Recreate the index.html") 135 | (docgen//create-file-from-list docgen//file-list-function "Functions") 136 | (docgen//create-file-from-list docgen//file-list-variable "Variables") 137 | (docgen//create-file-from-list docgen//file-list-face "Faces")) 138 | 139 | (defun docgen//create-file-from-list (list file) 140 | "Convert the cons LIST into a FILE listing all links of the type." 141 | (let ((name (concat docgen//outdir (downcase file) ".html")) 142 | (header (expand-file-name "header.htmlt" docgen//outdir)) 143 | (footer (expand-file-name "footer.htmlt" docgen//outdir))) 144 | (with-temp-file name 145 | (insert-file-contents-literally header) 146 | (goto-char (point-max)) 147 | (insert (docgen//cons-list-to-item-list docgen//file-list-function file)) 148 | (goto-char (point-max)) 149 | (insert-file-contents-literally footer)))) 150 | 151 | ;; (defun docgen//faces-file-create () 152 | ;; (docgen//log "First, let's require all built-in features. So we know everything is defined.") 153 | ;; (mapc 154 | ;; (lambda (f) (condition-case nil 155 | ;; (progn (message "%s" f) 156 | ;; (require f nil t)) 157 | ;; (error nil))) ;;no-error because some features are obsolete and throw errors. 158 | ;; (docgen//full-feature-lister)) 159 | ;; ;; These lists will be used to create the functions.html and variables.html files 160 | ;; (setq docgen//file-list-variable nil 161 | ;; docgen//file-list-function nil 162 | ;; docgen//file-list-face nil) 163 | ;; (let ((docgen//sql-table-name "Faces") 164 | ;; (docgen//description 'docgen//describe-face) 165 | ;; (docgen//format "Face/%s.html") 166 | ;; (fill-column 1000) 167 | ;; (docgen//file-list 'docgen//file-list-face) 168 | ;; (fun (concat docgen//outdir "functions.html")) 169 | ;; (var (concat docgen//outdir "variables.html")) 170 | ;; (face (concat docgen//outdir "faces.html")) 171 | ;; (header (concat docgen//outdir "header.htmlt")) 172 | ;; (footer (concat docgen//outdir "footer.htmlt"))) 173 | ;; (mapc 174 | ;; (lambda (s) 175 | ;; (let* ((file (format docgen//format (docgen//clean-symbol s))) 176 | ;; (path (concat docgen//outdir file))) 177 | ;; (add-to-list docgen//file-list (cons (symbol-name s) (url-hexify-string file))))) 178 | ;; (docgen//face-list)) 179 | ;; (with-temp-file face 180 | ;; (insert-file-contents-literally header) 181 | ;; (goto-char (point-max)) 182 | ;; (insert (docgen//cons-list-to-item-list docgen//file-list-face "Faces")) 183 | ;; (goto-char (point-max)) 184 | ;; (insert-file-contents-literally footer)))) 185 | 186 | 187 | (defun docgen//log (&rest r) 188 | "" 189 | (when docgen//verbose 190 | (apply 'message r))) 191 | 192 | (defvar docgen//format nil) 193 | 194 | (defvar docgen//file-list nil) 195 | 196 | (defvar docgen//sql-table-name nil) 197 | 198 | (defvar docgen//documentation-template nil) 199 | 200 | (defun docgen//symbol-to-file (s) 201 | "Takes a symbol, produces an html file with the description. 202 | 203 | The content of the file is the description given by the function 204 | `docgen//description'. Since `describe-function' (and variable) is 205 | pretty slow, this is where most of the time is spent. 206 | 207 | The name of the file is a slightly sanitized version of the 208 | symbol name, since symbol names in elisp can be almost anything. 209 | The symbol name and file name will later be used for creating a 210 | list of links, so a cons cell like (SYMBOLNAME . FILE) is stored 211 | in the variable `docgen//file-list'." 212 | (let* ((file (format docgen//format (docgen//clean-symbol s))) 213 | (path (expand-file-name file docgen//outdir)) 214 | ;; For some reason some symbols which are fbound throw errors 215 | ;; when calling describe-function (in my case that happened 216 | ;; with bookmark-map). This is to skip those symbols: 217 | (doc (ignore-errors (funcall docgen//description s)))) 218 | (when doc 219 | (docgen//log "%5d / %d - %s" (setq docgen//count (1+ docgen//count)) docgen//total s) 220 | (with-temp-file path 221 | (insert 222 | (format docgen//documentation-template doc)) 223 | (set-buffer-file-coding-system 'no-conversion)) 224 | (push (cons (symbol-name s) 225 | (format docgen//format (url-hexify-string (docgen//clean-symbol s)))) 226 | docgen//file-list) 227 | (append-to-file 228 | (docgen//format-sql-command docgen//sql-insert-string 229 | docgen//sql-table-name (symbol-name s) 0) 230 | nil docgen//sql-script-file)))) 231 | 232 | (defun docgen//format-sql-command (fs &rest strings) 233 | "Double any quotes inside STRINGS, then use them in FS as a regular format string." 234 | (apply 'format fs 235 | (mapcar 236 | (lambda (x) (replace-regexp-in-string "'" "''" (format "%s" x))) 237 | strings))) 238 | 239 | (defun docgen//clean-symbol (s) 240 | "This cleans the symbol a little bit, so it can be used as a file name. 241 | Fortunately gh-pages seems to use a linux file system, so the 242 | only forbidden character is the /." 243 | (replace-regexp-in-string 244 | "/" "%_%" 245 | (replace-regexp-in-string 246 | "%" "%%" (symbol-name s)))) 247 | 248 | (defun docgen//clean-string (s) 249 | "This cleans the symbol a little bit, so it can be used as a file name. 250 | Fortunately gh-pages seems to use a linux file system, so the 251 | only forbidden character is the /." 252 | (replace-regexp-in-string 253 | "/" "%_%" 254 | (replace-regexp-in-string 255 | "%" "%%" s))) 256 | 257 | (defun docgen//function-list () 258 | "" 259 | (docgen//-list-all 'fboundp)) 260 | 261 | (defun docgen//variable-list () 262 | "" 263 | (docgen//-list-all 'boundp)) 264 | 265 | (defun docgen//face-list () 266 | "" 267 | (docgen//-list-all 'facep)) 268 | 269 | (defun docgen//-list-all (docgen//predicate) 270 | "List all internal symbols satifying the DOCGEN//PREDICATE. 271 | 272 | The whole process (name, difference, sorting, reversing, 273 | internalize) is far from optimized. But the rest of the script is 274 | 1000 times slower than this, so it doesn't really matter." 275 | (let ((docgen//temp 276 | (mapcar 277 | 'intern-soft 278 | (nreverse ;;Reversing the sort order guarantees the links will be created in the right order later. 279 | (cl-sort ;;We sort now because it's easier, so the final list of links will be sorted. 280 | (loop for docgen//my-unique-var being the symbols 281 | if (and (null (string-match "\\`docgen//" (symbol-name docgen//my-unique-var))) 282 | (funcall docgen//predicate docgen//my-unique-var)) 283 | collect (symbol-name docgen//my-unique-var)) 284 | 'string< :key 'downcase))))) 285 | (when docgen//verbose 286 | (setq docgen//count 0) 287 | (setq docgen//total (length docgen//temp))) 288 | docgen//temp)) 289 | 290 | (defun docgen//describe-variable (variable) 291 | "Generate the full documentation of VARIABLE (a symbol) as html. 292 | Returns the documentation as a string." 293 | (let ((buffer (current-buffer)) 294 | (file-name (find-lisp-object-file-name variable 'defvar))) 295 | (with-temp-buffer 296 | (save-excursion 297 | (let ((valvoid (not (boundp variable))) 298 | (permanent-local (get variable 'permanent-local)) 299 | (val (symbol-value variable)) 300 | (locus (variable-binding-locus variable)) 301 | val-start-pos) 302 | (insert 303 | "" (symbol-name variable) "" 304 | (if file-name 305 | (concat 306 | " is a variable defined in `" "" 307 | (if (eq file-name 'C-source) 308 | "C source code" 309 | (file-name-nondirectory file-name)) 310 | "" "'.
\n" 311 | (if valvoid "It is void as a variable." "Its ")) 312 | (if valvoid " is void as a variable." "'s "))) 313 | 314 | (unless valvoid 315 | (setq val-start-pos (point)) 316 | (insert "value is ") 317 | (let ((from (point)) 318 | (line-beg (line-beginning-position)) 319 | (print-rep 320 | (let ((print-quoted t)) 321 | (prin1-to-string val))) 322 | fits) 323 | (setq fits (< (+ (length print-rep) (point) (- line-beg)) 68)) 324 | (insert "
")
325 |               (if fits (insert print-rep)
326 |                 (insert "
\n") 327 | (pp val 'insert) 328 | ;; ;; Not sure what this did 329 | ;; (if (< (point) (+ 68 (line-beginning-position 0))) 330 | ;; (delete-region from (1+ from)) 331 | ;; (delete-region (1- from) from)) 332 | ) 333 | (insert "
") 334 | (let* ((sv (get variable 'standard-value)) 335 | (origval (and (consp sv) 336 | (condition-case nil 337 | (eval (car sv)) 338 | (error :help-eval-error))))) 339 | (when (and (consp sv) 340 | (not (equal origval val)) 341 | (not (equal origval :help-eval-error))) 342 | (insert "
\nOriginal value was
\n
")
343 |                   (setq from (point))
344 |                   (pp origval 'insert)
345 |                   (if (< (point) (+ from 20))
346 |                       (delete-region (1- from) from))
347 |                   (insert "
"))))) 348 | (insert "
\n") 349 | 350 | (when locus 351 | (cond 352 | ((framep locus) (insert "It is a frame-local variable; ")) 353 | ((terminal-live-p locus) (insert "It is a terminal-local variable; ")) 354 | (t)) 355 | (if (not (default-boundp variable)) 356 | (insert "globally void") 357 | (let ((global-val (default-value variable))) 358 | (insert "global value is ") 359 | (if (eq val global-val) 360 | (insert "the same.") 361 | (insert "
\n
")
362 |                   (let ((from (point)))
363 |                     (pp global-val 'insert)
364 |                     (if (< (point) (+ from 20))
365 |                         (delete-region (1- from) from)))
366 |                   (insert "
")))) 367 | (insert "
\n")) 368 | 369 | ;; If the value is large, move it to the end. 370 | (when (> (count-lines (point-min) (point-max)) 10) 371 | ;; Note that setting the syntax table like below 372 | ;; makes forward-sexp move over a `'s' at the end 373 | ;; of a symbol. 374 | (set-syntax-table emacs-lisp-mode-syntax-table) 375 | (goto-char val-start-pos) 376 | (when (looking-at "value is") (replace-match "")) 377 | (save-excursion 378 | (insert "
\n
\nValue:")) 379 | (insert "value is shown " 380 | "below" 381 | ".
\n")) 382 | 383 | (let* ((alias (condition-case nil 384 | (indirect-variable variable) 385 | (error variable))) 386 | (obsolete (get variable 'byte-obsolete-variable)) 387 | (use (car obsolete)) 388 | (safe-var (get variable 'safe-local-variable)) 389 | (doc (or (documentation-property 390 | variable 'variable-documentation) 391 | (documentation-property 392 | alias 'variable-documentation))) 393 | (extra-line nil)) 394 | 395 | ;; Mention if it's a local variable. 396 | (insert "