From 3a3f528772b2ecc86f3be0657d0116790c2022aa Mon Sep 17 00:00:00 2001 From: Mark Oteiza Date: Fri, 6 Feb 2015 19:49:01 -0500 Subject: [PATCH 1/2] Add info manual --- create-docs.sh | 1 + dash-template.texi | 438 ++++++++++++++++++++++++++++++++++++++++ dev/examples-to-info.el | 175 ++++++++++++++++ 3 files changed, 614 insertions(+) create mode 100644 dash-template.texi create mode 100644 dev/examples-to-info.el diff --git a/create-docs.sh b/create-docs.sh index dbaae5c..804b375 100755 --- a/create-docs.sh +++ b/create-docs.sh @@ -5,3 +5,4 @@ if [ -z "$EMACS" ] ; then fi $EMACS -batch -l dash.el -l dash-functional.el -l dev/examples-to-docs.el -l dev/examples.el -f create-docs-file +$EMACS -batch -l dash.el -l dash-functional.el -l dev/examples-to-info.el -l dev/examples.el -f create-info-file diff --git a/dash-template.texi b/dash-template.texi new file mode 100644 index 0000000..ea0339b --- /dev/null +++ b/dash-template.texi @@ -0,0 +1,438 @@ +\input texinfo @c -*- texinfo -*- +@c %**start of header +@setfilename dash.info +@settitle dash +@documentencoding UTF-8 +@documentlanguage en +@syncodeindex fn cp +@c %**end of header + +@copying + +This manual is for @code{dash.el} version 2.10.0. + +Copyright © 2012-2015 Magnar Sveen + +@quotation +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see @uref{http://www.gnu.org/licenses/}. +@end quotation +@end copying + +@finalout +@titlepage +@title Dash +@author Magnar Sveen +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@contents + +@ifnottex +@node Top +@top dash +@insertcopying +@end ifnottex + +@menu +* Installation:: +* Functions:: +* Development:: +* Index:: + +@detailmenu +--- The Detailed Node Listing --- + +Installation + +* Using in a package:: +* Syntax highlighting of dash functions:: + +Functions + +@c [[ function-nodes ]] + +Development + +* Contribute:: How to contribute +* Changes:: List of significant changes by version +* Contributors:: List of contributors +@end detailmenu +@end menu + + + +@node Installation +@chapter Installation + +It's available on @uref{http://marmalade-repo.org/,marmalade} and +@uref{http://melpa.milkbox.net/,Melpa}; use @code{M-x +package-install}: + +@table @kbd +@item M-x package-install @key{RET} dash +Install the dash library. +@end table + +@table @kbd +@item M-x package-install @key{RET} dash-functional +Optional, if you want the function combinators. +@end table + +Alternatively, you can just dump @verb{~dash.el~} or +@verb{~dash-functional.el~} in your load path somewhere. + +@menu +* Using in a package:: +* Syntax highlighting of dash functions:: +@end menu + +@node Using in a package +@section Using in a package + +Add this to the big comment block at the top: + +@lisp +;; Package-Requires: ((dash "2.10.0")) +@end lisp + +@noindent To get function combinators: + +@lisp +;; Package-Requires: ((dash "2.10.0") (dash-functional "1.2.0") (emacs "24")) +@end lisp + +@node Syntax highlighting of dash functions +@section Syntax highlighting of dash functions + +Font lock of dash functions in emacs lisp buffers is now optional. +Include this in your emacs settings to get syntax highlighting: + +@lisp +(eval-after-load "dash" '(dash-enable-font-lock)) +@end lisp + +@node Functions +@chapter Functions + +This chapter contains reference documentation for the dash +@abbr{application programming interface,API}. All functions and +constructs in the library are prefixed with a dash (-). + +There are also anaphoric versions of functions where that makes sense, +prefixed with two dashes instead of one. + +For instance, while @code{-map} takes a function to map over the list, +one can also use the anaphoric form with double dashes - which will +then be executed with @code{it} exposed as the list item. Here's an +example: + +@lisp +(-map (lambda (n) (* n n)) '(1 2 3 4)) ;; normal version + +(--map (* it it) '(1 2 3 4)) ;; anaphoric version +@end lisp + +@noindent Of course, the original can also be written like + +@lisp +(defun square (n) (* n n)) + +(-map 'square '(1 2 3 4)) +@end lisp + +@noindent which demonstrates the usefulness of both versions. + +@menu +@c [[ function-nodes ]] +@end menu + +@c [[ function-docs ]] + +@node Development +@chapter Development + +The dash repository is hosted on GitHub: +@uref{https://github.com/magnars/dash.el} + +@menu +* Contribute:: How to contribute +* Changes:: List of significant changes by version +* Contributors:: List of contributors +@end menu + +@node Contribute +@section Contribute + +Yes, please do. Pure functions in the list manipulation realm only, +please. There's a suite of tests in @verb{~dev/examples.el~}, so remember to add +tests for your function, or it might get broken later. + +Run the tests with @code{./run-tests.sh}. Create the docs with +@code{./create-docs.sh}. I highly recommend that you install these as a +pre-commit hook, so that the tests are always running and the docs are +always in sync: + +@verbatim +cp pre-commit.sh .git/hooks/pre-commit +@end verbatim + +Oh, and don't edit @file{README.md} directly, it is auto-generated. +Change @file{readme-template.md} or @file{examples-to-docs.el} +instead. The same goes for the info manual. + +@node Changes +@section Changes + +@noindent Changes in 2.10: + +@itemize +@item +Add @code{-let} destructuring to @code{-if-let} and @code{-when-let} +(Fredrik Bergroth) +@end itemize + +@noindent Changes in 2.9: + +@itemize +@item +Add @code{-let}, @code{-let*} and @code{-lambda} with destructuring +@item +Add @code{-tree-seq} and @code{-tree-map-nodes} +@item +Add @code{-non-nil} +@item +Add @code{-fix} +@item +Add @code{-fixfn} (dash-functional 1.2) +@item +Add @code{-copy} (Wilfred Hughes) +@end itemize + +@noindent Changes in 2.8: + +@itemize +@item +Add @code{-butlast} +@end itemize + +@noindent Changes in 2.7: + +@itemize +@item +@code{-zip} now supports more than two lists (Steve Lamb) +@item +Add @code{-cycle}, @code{-pad}, @code{-annotate}, @code{-zip-fill} +(Steve Lamb) +@item +Add @code{-table}, @code{-table-flat} (finite cartesian product) +@item +Add @code{-flatten-n} +@item +@code{-slice} now supports "step" argument +@item +Add functional combinators @code{-iteratefn}, @code{-prodfn} +@item +Add @code{-replace}, @code{-splice}, @code{-splice-list} which +generalize @code{-replace-at} and @code{-insert-at} +@item +Add @code{-compose}, @code{-iteratefn} and @code{-prodfn} +(dash-functional 1.1) +@end itemize + +@noindent Changes in 2.6: + +@itemize +@item +Add @code{-is-prefix-p}, @code{-is-suffix-p}, @code{-is-infix-p} +(Matus Goljer) +@item +Add @code{-iterate}, @code{-unfold} (Matus Goljer) +@item +Add @code{-split-on}, @code{-split-when} (Matus Goljer) +@item +Add @code{-find-last-index} (Matus Goljer) +@item +Add @code{-list} (Johan Andersson) +@end itemize + +@noindent Changes in 2.5: + +@itemize +@item +Add @code{-same-items?} (Johan Andersson) +@item +A few bugfixes +@end itemize + +@noindent Changes in 2.4: + +@itemize +@item +Add @code{-snoc} (Matus Goljer) +@item +Add @code{-replace-at}, @code{-update-at}, @code{-remove-at}, and +@code{-remove-at-indices} (Matus Goljer) +@end itemize + +@noindent Changes in 2.3: + +@itemize +@item +Add tree operations (Matus Goljer) +@item +Make font-lock optional +@end itemize + +@noindent Changes in 2.2: + +@itemize +@item +Add @code{-compose} (Christina Whyte) +@end itemize + +@noindent Changes in 2.1: + +@itemize +@item +Add indexing operations (Matus Goljer) +@end itemize + +@noindent Changes in 2.0: + +@itemize +@item +Split out @code{dash-functional.el} (Matus Goljer) +@item +Add @code{-andfn}, @code{-orfn}, @code{-not}, @code{-cut}, +@code{-const}, @code{-flip} and @code{-on}. (Matus Goljer) +@item +Fix @code{-min}, @code{-max}, @code{-min-by} and @code{-max-by} (Matus +Goljer) +@end itemize + +@noindent Changes in 1.8: + +@itemize +@item +Add @code{-first-item} and @code{-last-item} (Wilfred Hughes) +@end itemize + +@noindent Changes in 1.7: + +@itemize +@item +Add @code{-rotate} (Matus Goljer) +@end itemize + +@noindent Changes in 1.6: + +@itemize +@item +Add @code{-min}, @code{-max}, @code{-min-by} and @code{-max-by} (Johan +Andersson) +@end itemize + +@noindent Changes in 1.5: + +@itemize +@item +Add @code{-sum} and @code{-product} (Johan Andersson) +@end itemize + +@noindent Changes in 1.4: + +@itemize +@item +Add @code{-sort} +@item +Add @code{-reduce-r} (Matus Goljer) +@item +Add @code{-reduce-r-from} (Matus Goljer) +@end itemize + +@noindent Changes in 1.3: + +@itemize +@item +Add @code{-partition-in-steps} +@item +Add @code{-partition-all-in-steps} +@end itemize + +@noindent Changes in 1.2: + +@itemize +@item +Add @code{-last} (Matus Goljer) +@item +Add @code{-insert-at} (Emanuel Evans) +@item +Add @code{-when-let} and @code{-if-let} (Emanuel Evans) +@item +Add @code{-when-let*} and @code{-if-let*} (Emanuel Evans) +@item +Some bugfixes +@end itemize + +@node Contributors +@section Contributors + +@itemize +@item +@uref{https://github.com/Fuco1,Matus Goljer} contributed lots of +features and functions. +@item +@uref{https://github.com/tkf,Takafumi Arakaki} contributed +@code{-group-by}. +@item +@uref{https://github.com/tali713,tali713} is the author of +@code{-applify}. +@item +@uref{https://github.com/vemv,Víctor M. Valenzuela} contributed +@code{-repeat}. +@item +@uref{https://github.com/nicferrier,Nic Ferrier} contributed +@code{-cons*}. +@item +@uref{https://github.com/Wilfred,Wilfred Hughes} contributed +@code{-slice}, @code{-first-item} and @code{-last-item}. +@item +@uref{https://github.com/shosti,Emanuel Evans} contributed +@code{-if-let}, @code{-when-let} and @code{-insert-at}. +@item +@uref{https://github.com/rejeep,Johan Andersson} contributed +@code{-sum}, @code{-product} and @code{-same-items?} +@item +@uref{https://github.com/kurisuwhyte,Christina Whyte} contributed +@code{-compose} +@item +@uref{https://github.com/steventlamb,Steve Lamb} contributed +@code{-cycle}, @code{-pad}, @code{-annotate}, @code{-zip-fill} and an +n-ary version of @code{-zip}. +@item +@uref{https://github.com/fbergroth,Fredrik Bergroth} made the +@code{-if-let} family use @code{-let} destructuring and improved +script for generating documentation. +@end itemize + +Thanks! + +@node Index +@unnumbered Index + +@printindex cp + +@bye diff --git a/dev/examples-to-info.el b/dev/examples-to-info.el new file mode 100644 index 0000000..8c67382 --- /dev/null +++ b/dev/examples-to-info.el @@ -0,0 +1,175 @@ +(require 'dash) +(require 'dash-functional) +(require 'help-fns) + +(defvar functions '()) + +(defun example-to-string (example) + (let ((actual (car example)) + (expected (nth 2 example))) + (--> (format "@group\n%S\n @result{} %S\n@end group" actual expected) + (replace-regexp-in-string "\\\\\\?" "?" it) + (replace-regexp-in-string "{\"" "@{\"" it t t) + (replace-regexp-in-string "}\"" "@}\"" it t t) + (replace-regexp-in-string " {" " @{" it t t) + (replace-regexp-in-string "\"{" "\"@{" it t t) + (replace-regexp-in-string "}," "@{," it t t) + (replace-regexp-in-string "}@}" "@}@}" it t t)))) + +(defun docs--signature (function) + "Given FUNCTION (a symbol), return its argument list. +FUNCTION may reference an elisp function, alias, macro or a subr." + (let* ((function-value (indirect-function function)) + (is-alias (not (eq function-value (symbol-function function)))) + ;; if FUNCTION isn't an alias, function-symbol is simply FUNCTION + (function-symbol function)) + + (when is-alias + ;; find the last symbol in the alias chain + (while (symbolp (symbol-function function-symbol)) + (setq function-symbol (symbol-function function-symbol)))) + + (if (subrp function-value) + ;; read the docstring to find the signature for subrs + (let* ((docstring-args (car (help-split-fundoc + (documentation function-value) + function-symbol))) + (fun-with-args (read (downcase docstring-args)))) + (cdr fun-with-args)) + ;; otherwise get the signature directly + (help-function-arglist function-symbol)))) + +(defmacro defexamples (cmd &rest examples) + `(add-to-list 'functions (list + ',cmd + (docs--signature ',cmd) + (documentation ',cmd) + (-map 'example-to-string (-partition 3 ',examples))))) + +(defmacro def-example-group (group desc &rest examples) + `(progn + (add-to-list 'functions ,(concat "### " group)) + (when ,desc + (add-to-list 'functions ,desc)) + ,@examples)) + +(defun quote-and-downcase (string) + (format "@var{%s}" (downcase string))) + +(defun unquote-and-link (string) + (format-link (substring string 1 -1))) + +(defun format-link (string-name) + (-let* ((name (intern string-name)) + ((_ signature _ _) (assoc name functions))) + (if signature + (format "@code{%s} (@pxref{%s})" name name) + (format "@code{%s}" name)))) + +(defun format-docstring (docstring) + (let (case-fold-search) + (--> docstring + (replace-regexp-in-string "\\b\\([A-Z][A-Z-]*[0-9]*\\)\\b" 'quote-and-downcase it t) + (replace-regexp-in-string "`\\([^ ]+\\)'" 'unquote-and-link it t) + (replace-regexp-in-string "{,@}" "{,@@}" it t) + (replace-regexp-in-string "^ " " " it)))) + +(defun function-to-node (function) + (when (and (stringp function) + (string-match "^\\(### [[:upper:]][[:alpha:]- ]+\\)$" function)) + (concat (s-replace "### " "* " (match-string 1 function)) "::"))) + +(defun function-to-info (function) + (if (stringp function) + (concat "\n" (s-replace "### " "@node " function) "\n" + (when (string-match "^### " function) + (s-replace "### " "@section " function)) "\n") + (-let [(command-name signature docstring examples) function] + (format (concat "@anchor{%s}\n" + "@defun %s %s\n" + "%s\n\n" + "@example\n%s\n@end example\n@end defun\n") + command-name + command-name + signature + (format-docstring docstring) + (mapconcat 'identity (-take 3 examples) "\n"))))) + +(defun docs--chop-prefix (prefix s) + "Remove PREFIX if it is at the start of S." + (let ((pos (length prefix))) + (if (and (>= (length s) (length prefix)) + (string= prefix (substring s 0 pos))) + (substring s pos) + s))) + +(defun docs--chop-suffix (suffix s) + "Remove SUFFIX if it is at end of S." + (let ((pos (- (length suffix)))) + (if (and (>= (length s) (length suffix)) + (string= suffix (substring s pos))) + (substring s 0 pos) + s))) + +(defun github-id (command-name signature) + (docs--chop-suffix + "-" + (replace-regexp-in-string "[^a-zA-Z0-9-]+" "-" (docs--chop-prefix + "!" + (format "%S %S" command-name signature))))) + +(defun s-replace (old new s) + "Replaces OLD with NEW in S." + (replace-regexp-in-string (regexp-quote old) new s t t)) + +(defun function-summary (function) + (if (stringp function) + (concat "\n" function "\n") + (let ((command-name (car function)) + (signature (cadr function))) + (format "* [%s](#%s) `%s`" command-name (github-id command-name signature) signature)))) + +(defun simplify-quotes () + (goto-char (point-min)) + (while (search-forward "(quote nil)" nil t) + (replace-match "'()")) + (goto-char (point-min)) + (while (search-forward "(quote " nil t) + (forward-char -7) + (let ((p (point))) + (forward-sexp 1) + (delete-char -1) + (goto-char p) + (delete-char 7) + (insert "'")))) + +(defun goto-and-remove (s) + (goto-char (point-min)) + (search-forward s) + (delete-char (- (length s)))) + +(defun create-info-file () + (let ((functions (nreverse functions))) + (with-temp-file "./dash.texi" + (insert-file-contents-literally "./dash-template.texi") + + (goto-and-remove "@c [[ function-nodes ]]") + (insert (mapconcat 'function-to-node + (-filter (lambda (s) + (when (stringp s) + (string-match "^### " s))) + functions) + "\n")) + + (goto-and-remove "@c [[ function-nodes ]]") + (insert (mapconcat 'function-to-node + (-filter (lambda (s) + (when (stringp s) + (string-match "^### " s))) + functions) + "\n")) + + (goto-and-remove "@c [[ function-docs ]]") + (insert (mapconcat 'function-to-info functions "\n")) + + (simplify-quotes)))) From 4bd6273d8660be3fcb05190ff8caf6c1d75a4de9 Mon Sep 17 00:00:00 2001 From: Mark Oteiza Date: Sat, 7 Feb 2015 09:29:04 -0500 Subject: [PATCH 2/2] Invoke makeinfo on the generated .texi --- create-docs.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/create-docs.sh b/create-docs.sh index 804b375..d24082d 100755 --- a/create-docs.sh +++ b/create-docs.sh @@ -4,5 +4,10 @@ if [ -z "$EMACS" ] ; then EMACS="emacs" fi +if [ -z "$MAKEINFO" ] ; then + MAKEINFO="makeinfo" +fi + $EMACS -batch -l dash.el -l dash-functional.el -l dev/examples-to-docs.el -l dev/examples.el -f create-docs-file $EMACS -batch -l dash.el -l dash-functional.el -l dev/examples-to-info.el -l dev/examples.el -f create-info-file +$MAKEINFO --fill-column=70 dash.texi