├── examples ├── emacs-muse.png ├── muse-made-with.png ├── mwolson │ ├── templates │ │ ├── generic-footer.html │ │ ├── generic-header.html │ │ ├── header.tex │ │ ├── header.html │ │ └── footer.html │ └── stylesheets │ │ ├── print.css │ │ ├── screen.css │ │ ├── blog.css │ │ └── common.css ├── johnw │ └── publish-johnw ├── publish-project ├── Makefile └── ikiwiki │ ├── muse-init-simple.el │ └── muse-init-project.el ├── scripts ├── publish └── muse-build.el ├── .gitignore ├── texi ├── dir-template └── Makefile ├── contrib ├── htmlize-hack.el ├── pyblosxom │ ├── make-blog │ ├── getstamps.py │ ├── hardcodedates.py │ └── metadate.py ├── Makefile ├── blosxom │ └── getstamps.pl ├── ikiwiki │ └── IkiWiki │ │ └── Plugin │ │ ├── muse.pm │ │ └── test.pl └── cgi.el ├── experimental ├── Makefile ├── muse-protocol-iw.el ├── muse-cite.el ├── muse-mathml.el └── muse-message.el ├── ChangeLog ├── Makefile.defs.default ├── Makefile ├── lisp ├── Makefile ├── muse-import-xml.el ├── muse-import-docbook.el ├── muse-import-latex.el ├── muse-ipc.el ├── muse-xml-common.el ├── muse-poem.el ├── muse-ikiwiki.el ├── muse-protocols.el ├── muse-http.el └── muse-regexps.el ├── etc ├── IDEAS.muse ├── emacs-wiki-migration.txt └── muse.rnc ├── AUTHORS └── README /examples/emacs-muse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexott/muse/HEAD/examples/emacs-muse.png -------------------------------------------------------------------------------- /examples/muse-made-with.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexott/muse/HEAD/examples/muse-made-with.png -------------------------------------------------------------------------------- /examples/mwolson/templates/generic-footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/johnw/publish-johnw: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Example publishing script for johnw's configuration 4 | 5 | style=$(echo $1 | sed 's/^--//') 6 | shift 7 | emacs -q -batch -L $(dirname $0) \ 8 | -l muse-build.el -l muse-johnw.el \ 9 | -f muse-batch-publish-files $style --output-dir=. "$@" 10 | -------------------------------------------------------------------------------- /scripts/publish: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | style=$(echo $1 | sed 's/^--//') 3 | shift 4 | $EMACS -q $SITEFLAG -batch -l ../scripts/muse-build.el \ 5 | -l muse-regexps.el -l muse.el -l muse-publish.el \ 6 | -l muse-html.el -l muse-latex.el -l muse-texinfo.el \ 7 | -f muse-batch-publish-files $style --output-dir=. "$@" 8 | -------------------------------------------------------------------------------- /examples/publish-project: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This is an example script that shows how to publish a project from 4 | # the commandline. 5 | # 6 | # Make sure that you have a file named `muse-init.el' that contains 7 | # your custom Muse settings. It should add Muse to the load path. 8 | 9 | emacs -q -batch -l muse-init.el -f muse-project-batch-publish "$@" 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Files that we ignore when using git. 2 | 3 | *~ 4 | /++xgit-log-edit 5 | *.elc 6 | /Makefile.defs 7 | /examples/QuickStart.html 8 | /examples/QuickStart.info 9 | /examples/QuickStart.pdf 10 | /lisp/muse-autoloads.el 11 | /texi/muse.info 12 | /texi/muse.html 13 | /texi/gendocs.sh 14 | /texi/gendocs_template 15 | /texi/muse.aux 16 | /texi/muse.cp 17 | /texi/muse.cps 18 | /texi/muse.fn 19 | /texi/muse.ky 20 | /texi/muse.log 21 | /texi/muse.pg 22 | /texi/muse.toc 23 | /texi/muse.tp 24 | /texi/muse.vr 25 | -------------------------------------------------------------------------------- /texi/dir-template: -------------------------------------------------------------------------------- 1 | This is the file .../info/dir, which contains the 2 | topmost node of the Info hierarchy, called (dir)Top. 3 | The first time you invoke Info you start off looking at this node. 4 |  5 | File: dir, Node: Top This is the top of the INFO tree 6 | 7 | This (the Directory node) gives a menu of major topics. 8 | Typing "q" exits, "?" lists all Info commands, "d" returns here, 9 | "h" gives a primer for first-timers, 10 | "mEmacs" visits the Emacs manual, etc. 11 | 12 | In Emacs, you can click mouse button 2 on a menu item or cross reference 13 | to select it. 14 | 15 | * Menu: 16 | -------------------------------------------------------------------------------- /texi/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all info-only doc clean realclean distclean fullclean install 2 | .PRECIOUS: %.info %.html 3 | 4 | DEFS = $(shell test -f ../Makefile.defs && echo ../Makefile.defs \ 5 | || echo ../Makefile.defs.default) 6 | 7 | include $(DEFS) 8 | 9 | all: doc 10 | 11 | %.info: %.texi 12 | makeinfo $< 13 | 14 | %.html: %.texi 15 | makeinfo --html --no-split $< 16 | 17 | info-only: $(MANUAL).info 18 | 19 | doc: $(MANUAL).info $(MANUAL).html 20 | 21 | clean: ; 22 | 23 | distclean realclean fullclean: clean 24 | -rm -f $(MANUAL).info $(MANUAL).html 25 | 26 | install: $(MANUAL).info 27 | [ -d $(INFODIR) ] || install -d $(INFODIR) 28 | install -m 0644 $(MANUAL).info $(INFODIR)/$(MANUAL) 29 | $(call install_info,$(MANUAL)) 30 | -------------------------------------------------------------------------------- /contrib/htmlize-hack.el: -------------------------------------------------------------------------------- 1 | ;; This file provides a fix for htmlize.el and Emacs 23. 2 | ;; To use it, add the path to this directory to your load path and 3 | ;; add (require 'htmlize-hack) to your Emacs init file. 4 | 5 | (require 'htmlize) 6 | 7 | (when (equal htmlize-version "1.34") 8 | (defun htmlize-face-size (face) 9 | ;; The size (height) of FACE, taking inheritance into account. 10 | ;; Only works in Emacs 21 and later. 11 | (let ((size-list 12 | (loop 13 | for f = face then (face-attribute f :inherit) 14 | until (or (null f) (eq f 'unspecified)) 15 | for h = (face-attribute f :height) 16 | collect (if (eq h 'unspecified) nil h)))) 17 | (reduce 'htmlize-merge-size (cons nil size-list))))) 18 | 19 | (provide 'htmlize-hack) 20 | -------------------------------------------------------------------------------- /contrib/pyblosxom/make-blog: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Author: Michael Olson 4 | # 5 | # License: This file may be used, distributed, and modified without 6 | # restriction. 7 | # 8 | # This is a sample script that shows how to update the timestamps 9 | # file. Note that you have to run the getstamps.py program in your 10 | # source directory, and then move the generated timestamps file to the 11 | # directory where your published entries are kept. 12 | 13 | # Blog entries in Muse format 14 | SRC_DIR=/stuff/proj/wiki/blog 15 | 16 | # Published blog entries 17 | DEST_DIR=$PWD/site/blog 18 | 19 | # Path to the getstamps.py script 20 | GETSTAMPS=$PWD/scripts/getstamps.py 21 | 22 | # Update timestamps for blog 23 | (cd $SRC_DIR && python $GETSTAMPS && mv timestamps $DEST_DIR/timestamps) 24 | -------------------------------------------------------------------------------- /contrib/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all contrib clean realclean distclean fullclean install 2 | .PRECIOUS: %.elc 3 | 4 | DEFS = $(shell test -f ../Makefile.defs && echo ../Makefile.defs \ 5 | || echo ../Makefile.defs.default) 6 | 7 | include $(DEFS) 8 | 9 | EL = $(wildcard *.el) 10 | EL_NOT_BYTE_COMPILED = htmlize-hack.el 11 | ELC = $(patsubst %.el,%.elc,$(filter-out $(EL_NOT_BYTE_COMPILED),$(EL))) 12 | 13 | all: contrib 14 | 15 | contrib: $(ELC) 16 | 17 | $(PROJECT)-build.elc: ../scripts/$(PROJECT)-build.el 18 | @echo $(PROJECT)-build.el is not byte-compiled 19 | 20 | %.elc: %.el 21 | @$(EMACS) -q $(SITEFLAG) -batch -l ../scripts/$(PROJECT)-build.el \ 22 | -f batch-byte-compile $< 23 | 24 | clean realclean distclean fullclean: 25 | -rm -f *.elc *~ 26 | 27 | install: $(ELC) 28 | install -d $(ELISPDIR)/contrib 29 | install -m 0644 $(EL) $(ELC) $(ELISPDIR)/contrib 30 | -------------------------------------------------------------------------------- /experimental/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all experimental clean realclean distclean fullclean install 2 | .PHONY: install-uncompiled 3 | .PRECIOUS: %.elc 4 | 5 | DEFS = $(shell test -f ../Makefile.defs && echo ../Makefile.defs \ 6 | || echo ../Makefile.defs.default) 7 | 8 | include $(DEFS) 9 | 10 | EL = $(wildcard *.el) 11 | ELC = $(patsubst %.el,%.elc,$(wildcard *.el)) 12 | 13 | all: experimental 14 | 15 | experimental: $(ELC) 16 | 17 | $(PROJECT)-build.elc: ../scripts/$(PROJECT)-build.el 18 | @echo $(PROJECT)-build.el is not byte-compiled 19 | 20 | %.elc: %.el 21 | @$(EMACS) -q $(SITEFLAG) -batch -l ../scripts/$(PROJECT)-build.el \ 22 | -f batch-byte-compile $< 23 | 24 | clean realclean distclean fullclean: 25 | -rm -f *.elc *~ 26 | 27 | install: $(ELC) 28 | install -d $(ELISPDIR)/experimental 29 | install -m 0644 $(EL) $(ELC) $(ELISPDIR)/experimental 30 | 31 | install-uncompiled: 32 | install -d $(ELISPDIR)/experimental 33 | install -m 0644 $(EL) $(ELISPDIR)/experimental 34 | -------------------------------------------------------------------------------- /examples/mwolson/stylesheets/print.css: -------------------------------------------------------------------------------- 1 | /* Michael Olson's tweaked Muse stylesheet 2 | 3 | Elements used when printing. 4 | 5 | License: Modification and propagation of this document is 6 | permitted. Attribution of credit to me is optional. 7 | */ 8 | 9 | html { 10 | font-family: Times, serif; 11 | font-size: 12pt; 12 | } 13 | 14 | body { 15 | margin-left: 1.5cm; 16 | margin-right: 1.5cm; 17 | margin-top: 1.5cm; 18 | margin-bottom: 1.5cm; 19 | } 20 | 21 | .menu, .menuitem, .navfoot, #tooltip, #tooltipbox { 22 | display: none; 23 | } 24 | 25 | a, a:visited, a.nonexistent, a.badinterwiki { 26 | color: black; 27 | text-decoration: none; 28 | } 29 | 30 | a:hover { 31 | text-decoration: underline; 32 | } 33 | 34 | dd { 35 | line-height: 2em; 36 | } 37 | 38 | h1 { 39 | border-right: 0; 40 | } 41 | 42 | h2 { 43 | border-right: 0; 44 | } 45 | 46 | h3 { 47 | border-right: 0; 48 | } 49 | 50 | h4 { 51 | border-right: 0; 52 | } 53 | 54 | img { 55 | display: none; 56 | } 57 | 58 | p { 59 | line-height: 2em; 60 | } 61 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all examples clean realclean distclean fullclean 2 | .PRECIOUS: %.html %.pdf %.info 3 | 4 | DEFS = $(shell test -f ../Makefile.defs && echo ../Makefile.defs \ 5 | || echo ../Makefile.defs.default) 6 | 7 | include $(DEFS) 8 | 9 | EXAMPLES = QuickStart.html QuickStart.pdf QuickStart.info 10 | 11 | all: examples 12 | 13 | examples: $(EXAMPLES) 14 | 15 | %.html: %.muse 16 | @echo Generating HTML for $<... 17 | EMACS=$(EMACS) SITEFLAG=$(SITEFLAG) ../scripts/publish html $< 18 | 19 | %.pdf: %.muse 20 | @echo Generating PDF for $< ... 21 | EMACS=$(EMACS) SITEFLAG=$(SITEFLAG) ../scripts/publish pdf $< 22 | 23 | %.info: %.muse 24 | @echo Generating Info for $< ... 25 | EMACS=$(EMACS) SITEFLAG=$(SITEFLAG) ../scripts/publish info $< 26 | 27 | clean: 28 | rm -f missfont.log QuickStart.texi *~ 29 | 30 | realclean distclean fullclean: clean 31 | rm -f $(EXAMPLES) 32 | rm -f QuickStart.aux QuickStart.log QuickStart.out QuickStart.tex 33 | rm -f QuickStart.cp QuickStart.fn QuickStart.ky QuickStart.pg 34 | rm -f QuickStart.tp QuickStart.vr 35 | -------------------------------------------------------------------------------- /examples/mwolson/templates/generic-header.html: -------------------------------------------------------------------------------- 1 | 2 | (muse-html-encoding)"?> 3 | 4 | 5 | 6 | <lisp> 7 | (let ((current-project 8 | (car (muse-project-of-file 9 | muse-publishing-current-file)))) 10 | (concat 11 | (when current-project 12 | (concat current-project " - ")) 13 | (muse-publishing-directive "title")))</lisp> 14 | 15 | 16 | 17 | 18 | 19 | 20 |

21 | (muse-wiki-publish-pretty-title)

22 | 23 | 24 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2009-08-05 Michael Olson 2 | 3 | * lisp/muse.el (muse-insert-file-contents): Cause epa-file-handler 4 | to be ignored. 5 | 6 | 2009-06-18 Michael Olson 7 | 8 | * lisp/muse-latex.el (muse-latex-slides-header) 9 | (muse-latex-lecture-notes-header): Handle images. Generate title 10 | page correctly. Generate table of contents page if requested. 11 | 12 | 2009-06-17 Michael Olson 13 | 14 | * lisp/muse-latex.el (muse-latex-pdf-cruft): Remove additional 15 | cruft files from beamer. 16 | 17 | 2009-01-03 Michael Olson 18 | 19 | * contrib/ikiwiki/Ikiwiki/Plugin/muse.pm: Move here from 20 | examples/ikiwiki/IkiWiki/Plugin/muse.pm. 21 | 22 | * contrib/Makefile (htmlize-hack.elc): Don't byte-compile 23 | htmlize-hack.el, since it is only useful if htmlize.el is 24 | installed. 25 | 26 | * contrib/cgi.el: Add compatibility functions for calendar, so 27 | that it works with both Emacs 21 and Emacs 23. Thanks to Brent 28 | Goodrick for the report. 29 | 30 | * texi/muse.texi (Using Muse Mode): Fix typo. 31 | 32 | 33 | See ChangeLog.5 for earlier changes. 34 | 35 | ;; Local Variables: 36 | ;; coding: utf-8 37 | ;; End: 38 | -------------------------------------------------------------------------------- /Makefile.defs.default: -------------------------------------------------------------------------------- 1 | # -*- Makefile -*- 2 | # 3 | # If you wish to modify this file, first copy it to a file called 4 | # Makefile.defs. The resulting Makefile.defs file may then be 5 | # modified. 6 | 7 | # Emacs options 8 | EMACS = emacs 9 | SITEFLAG = --no-site-file 10 | 11 | # XEmacs users will probably want the following settings. 12 | #EMACS = xemacs 13 | #SITEFLAG = -no-site-file 14 | 15 | # Installation options 16 | # PREFIX is only used here. 17 | DESTDIR = 18 | PREFIX = /usr/local 19 | ELISPDIR = $(DESTDIR)$(PREFIX)/share/emacs/site-lisp/muse 20 | INFODIR = $(DESTDIR)$(PREFIX)/share/info 21 | 22 | # Command to use to install the Info dir entry 23 | install_info = install-info --info-dir=$(INFODIR) $(1) || : 24 | 25 | # If you're using Debian or Ubuntu, uncomment the following rule and 26 | # comment out the previous rule. 27 | # 28 | #install_info = install-info --section "Emacs" "emacs" --info-dir=$(INFODIR) \ 29 | # $(INFODIR)/$(1) || : 30 | 31 | # If you're using XEmacs, use something like the following instead of 32 | # the above two rules. 33 | # 34 | #install_info = install-info --section "XEmacs 21.4" $(1).info \ 35 | # $(INFODIR)/dir || : 36 | 37 | # Useful only for the maintainer 38 | PROJECT = muse 39 | VERSION = 3.20 40 | MANUAL = muse 41 | 42 | # Location of Emacs Lisp Package Archive entries 43 | ELPADIR = ../../elpa 44 | # Description of ELPA package 45 | ELPADESC = Authoring and publishing tool 46 | -------------------------------------------------------------------------------- /examples/ikiwiki/muse-init-simple.el: -------------------------------------------------------------------------------- 1 | ;;; muse-init-simple.el --- Use Emacs Muse to publish ikiwiki documents 2 | 3 | ;; The code in this file may be used, distributed, and modified 4 | ;; without restriction. 5 | 6 | ;;; Setup 7 | 8 | (add-to-list 'load-path (expand-file-name "~ikiwiki/elisp/muse/lisp")) 9 | 10 | ;; Initialize 11 | (require 'muse) ; load generic module 12 | (require 'muse-html) ; load (X)HTML publishing style 13 | (require 'muse-ikiwiki) ; load Ikiwiki integration 14 | 15 | ;;; Settings 16 | 17 | ;; Permitted modes for to colorize 18 | (setq muse-html-src-allowed-modes 19 | '("ada" "apache" "asm" "awk" "c++" "c" "cc" "change-log" "context" 20 | "css" "diary" "diff" "dns" "domtool" "emacs-lisp" "f90" "fortran" 21 | "fundamental" "html" "java" "jython" "latex" "lisp" "lua" "m4" 22 | "makefile" "markdown" "matlab" "maxima" "message" "modula-2" "muse" 23 | "nroff" "octave" "org" "outline" "pascal" "perl" "ps" "python" "rst" 24 | "ruby" "scheme" "sgml" "sh" "slang" "sml" "sml-cm" "sml-lex" "sml-yacc" 25 | "sql" "tcl" "tex" "texinfo" "xml" "zone")) 26 | ;; In case someone does 27 | (setq muse-colors-evaluate-lisp-tags nil 28 | muse-colors-inline-images nil) 29 | ;; In case someone does 30 | (require 'org) 31 | (setq org-inhibit-startup t 32 | org-table-formula-evaluate-inline nil) 33 | 34 | ;; Don't allow dangerous tags to be published 35 | (setq muse-publish-enable-dangerous-tags nil) 36 | 37 | ;;; Custom variables 38 | 39 | (custom-set-variables 40 | '(muse-html-charset-default "utf-8") 41 | '(muse-html-encoding-default (quote utf-8)) 42 | '(muse-html-meta-content-encoding (quote utf-8)) 43 | '(muse-publish-comments-p t) 44 | '(muse-publish-date-format "%b. %e, %Y")) 45 | (custom-set-faces) 46 | 47 | ;;; muse-init-simple.el ends here 48 | -------------------------------------------------------------------------------- /examples/mwolson/stylesheets/screen.css: -------------------------------------------------------------------------------- 1 | /* Michael Olson's tweaked Muse stylesheet 2 | 3 | Elements for most of my web site. 4 | 5 | License: Modification and propagation of this document is 6 | permitted. Attribution of credit to me is optional. 7 | */ 8 | 9 | /* Table of Contents */ 10 | 11 | .contents { 12 | clear: left; 13 | float: left; 14 | background-color: #D3D3D3; /* light gray */ 15 | border: 1px solid black; 16 | margin-top: 0; 17 | margin-right: 5px; 18 | margin-left: 0; 19 | margin-bottom: 15px; 20 | padding: 3px; 21 | } 22 | 23 | .contents dl { 24 | background-color: #F5F5F5; /* white smoke */ 25 | display: block; 26 | float: left; 27 | font-size: small; 28 | margin-top: 0; 29 | margin-bottom: 0; 30 | padding-bottom: 5px; 31 | } 32 | 33 | .contents dt { 34 | clear: left; 35 | display: block; 36 | padding-right: 5px; 37 | padding-left: 5px; 38 | text-align: left; 39 | } 40 | 41 | .contents dd dt { 42 | display: list-item; 43 | } 44 | 45 | .contents a:hover { 46 | background-color: #D3D3D3; /* light gray */ 47 | } 48 | 49 | /* Planner */ 50 | 51 | .taskA { color: red } 52 | 53 | .taskB { color: green } 54 | 55 | .taskC { color: navy } 56 | 57 | .taskX { 58 | color: #696969; /* dim gray */ 59 | text-decoration: line-through; 60 | } 61 | 62 | /* Source coloring */ 63 | 64 | .builtin { 65 | /* font-lock-builtin-face */ 66 | color: #9370db; 67 | } 68 | 69 | .comment { 70 | /* font-lock-comment-face */ 71 | color: #b22222; 72 | } 73 | 74 | .constant { 75 | /* font-lock-constant-face */ 76 | color: #b8860b; 77 | } 78 | 79 | .doc { 80 | } 81 | 82 | .function-name { 83 | /* font-lock-function-name-face */ 84 | color: #0000ff; 85 | } 86 | 87 | .keyword { 88 | /* font-lock-keyword-face */ 89 | color: #a020f0; 90 | } 91 | 92 | .string { 93 | /* font-lock-string-face */ 94 | color: #228b22; 95 | } 96 | -------------------------------------------------------------------------------- /contrib/blosxom/getstamps.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w -- 2 | 3 | # 4 | # $Id: getstamps.pl,v 1.3 2007-08-19 13:46:54 welle Exp $ 5 | # 6 | 7 | # Author: Michael Welle 8 | 9 | # This file is available under the terms of the GNU General Public 10 | # License, Version 2. 11 | 12 | # Modified by Michael Olson to add Author note. license text, and to 13 | # fix a use of "muse" rather than $muse_file_extension. 14 | 15 | #my $tsfile = "/tmp/blog/timestamps"; 16 | my $tsfile = "-"; 17 | my $muse_file_extension = "muse"; 18 | 19 | # 20 | # 21 | # 22 | sub process_file { 23 | my ($file) = @_; 24 | 25 | 26 | open( F, "<$file" ); 27 | 28 | while ( ) { 29 | 30 | if ( /^#date\s+(.+)$/ ) { 31 | 32 | close ( F ); 33 | my $d = $1; 34 | 35 | $file =~ s/\.${muse_file_extension}$/\.txt/; 36 | $file =~ s/^\.\///; 37 | 38 | if ( $d =~ /(\d\d\d\d)-(\d\d)-(\d\d)-(\d\d)-(\d\d)/ ) { 39 | 40 | printf TS "${file}=>$2/$3/$1 $4:$5\n"; 41 | return; 42 | 43 | } # if 44 | 45 | } # if 46 | 47 | } # while 48 | 49 | close( F ); 50 | 51 | } # process_file 52 | 53 | 54 | 55 | # 56 | # 57 | # 58 | sub traverse_directory { 59 | my ($directory) = @_; 60 | local *DIR; 61 | my @files = (); 62 | my $pfad = ""; 63 | 64 | 65 | opendir( DIR, $directory ); 66 | @files = readdir( DIR ); 67 | closedir( DIR ); 68 | 69 | 70 | foreach my $file ( @files ) { 71 | 72 | next if ( !( $file =~ /^.*\.${muse_file_extension}$/ ) 73 | || ($file eq '.') || ($file eq '..')); 74 | 75 | 76 | $path = "$directory/$file"; 77 | 78 | if( -d $path ) { 79 | 80 | traverse_directory( $path ); 81 | 82 | } else { 83 | 84 | process_file( $path ); 85 | 86 | } #if 87 | 88 | } #foreach 89 | 90 | } # traverse_directory 91 | 92 | 93 | # 94 | # Here we go... 95 | # 96 | 97 | open( TS, ">${tsfile}" ); 98 | 99 | if ( @ARGV == 0 ) { 100 | 101 | traverse_directory( "." ); 102 | 103 | } else { 104 | 105 | traverse_directory( $ARGV[0] ); 106 | 107 | } #if 108 | 109 | close( TS ); 110 | 111 | exit 0; 112 | -------------------------------------------------------------------------------- /examples/mwolson/templates/header.tex: -------------------------------------------------------------------------------- 1 | \documentclass 2 | (or (and (muse-publishing-directive "latex-twocolumn") 3 | "[twocolumn]") 4 | "") 5 | { 6 | (or (muse-publishing-directive "latex-document-class") 7 | "article")} 8 | 9 | \usepackage[english]{babel} 10 | \usepackage{amsfonts, amsmath, amssymb} 11 | \usepackage{ucs} 12 | 13 | % I'd love to be able to use CB fonts for Greek letters instead, as 14 | % the ucs docs recommend, but i couldn't figure it out 15 | \SetUnicodeOption{mathletters} 16 | 17 | % define Unicode "middle dot" to be TeX \cdot 18 | \DeclareUnicodeCharacter{183}{\ensuremath{\cdot}} 19 | % declare Unicode "maplet" to be TeX \mapsto 20 | \DeclareUnicodeCharacter{8614}{\ensuremath{\mapsto}} 21 | % declare Unicode "leftwards arrow with hook" to be TeX \hookleftarrow 22 | \DeclareUnicodeCharacter{8617}{\ensuremath{\hookleftarrow}} 23 | % declare Unicode "downwards double arrow" to be TeX \Downarrow 24 | \DeclareUnicodeCharacter{8659}{\ensuremath{\Downarrow}} 25 | % define Unicode "white circle" to be TeX \circ 26 | \DeclareUnicodeCharacter{9675}{\ensuremath{\circ}} 27 | 28 | \usepackage[utf8x]{inputenc} 29 | \usepackage[T1]{fontenc} 30 | \usepackage{hyperref} 31 | \usepackage[pdftex]{graphicx} 32 | 33 | \def\museincludegraphics{% 34 | \begingroup 35 | \catcode`\|=0 36 | \catcode`\\=12 37 | \catcode`\#=12 38 | \includegraphics[width=0.75\textwidth] 39 | } 40 | 41 | % One-inch margins 42 | \usepackage{fullpage} 43 | 44 | % A more PDF-friendly font 45 | \usepackage{lmodern} 46 | 47 | % An alternate, blockier font, should I ever want it 48 | % \renewcommand{\familydefault}{\sfdefault} \sf 49 | 50 | (when (muse-publishing-directive "latex-block-paragraphs") 51 | "\\setlength{\\parindent}{0pt} 52 | \\setlength{\\parskip}{4pt}") 53 | 54 | 55 | % For two-column documents, increase center margin to something readable 56 | \setlength{\columnsep}{.25in} 57 | 58 | \begin{document} 59 | 60 | (unless (muse-publishing-directive "latex-omit-title") 61 | (concat "\\title{" (muse-publish-escape-specials-in-string 62 | (muse-wiki-publish-pretty-title) 'document) "} 63 | \\author{" (muse-publishing-directive "author") "} 64 | \\date{" (muse-publishing-directive "date") "} 65 | 66 | \\maketitle")) 67 | 68 | 69 | (and muse-publish-generate-contents 70 | "\\tableofcontents 71 | \\clearpage") 72 | -------------------------------------------------------------------------------- /experimental/muse-protocol-iw.el: -------------------------------------------------------------------------------- 1 | ;;; muse-protocol-iw.el --- implement an interwiki protocol handler 2 | 3 | ;; Copyright (C) 2006 Free Software Foundation, Inc. 4 | 5 | ;; Author: Phillip Lord 6 | 7 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 8 | 9 | ;; Emacs Muse is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published 11 | ;; by the Free Software Foundation; either version 3, or (at your 12 | ;; option) any later version. 13 | 14 | ;; Emacs Muse is distributed in the hope that it will be useful, but 15 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | ;; General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 21 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 | ;; Boston, MA 02110-1301, USA. 23 | 24 | ;;; Commentary: 25 | 26 | ;; This defines a new url type, which is like the interwiki support of 27 | ;; muse-wiki. You can also publish to a different directory structure 28 | ;; from the file space (which I do for historical reasons). So a link 29 | ;; like 30 | 31 | ;; [[iw:home\emacs][hello]] will work from any of the individual muse 32 | ;; projects that I have. 33 | 34 | (require 'muse-protocols) 35 | 36 | (add-to-list 'muse-url-protocols 37 | '("iw:" muse-browse-url-iw muse-resolve-url-iw)) 38 | 39 | (defvar muse-interwiki-protocol-alist 40 | '(("home" "/" "~/src/ht/home_website") 41 | ("silly" "/silly/" "~/src/ht/home_website/silly") 42 | ("energy" "/energy/" "~/src/ht/home_website/energy") 43 | ("journal" "/journal/" "~/src/ht/home_website/journal"))) 44 | 45 | (defun muse-resolve-url-iw (url) 46 | (when (string-match "\\`iw:\\([a-zA-Z]*\\)\\\\\\(.+\\)" url) 47 | (let* ((wiki-resolve 48 | (assoc (match-string 1 url) 49 | muse-interwiki-protocol-alist)) 50 | (publish-resolve 51 | (nth 1 wiki-resolve))) 52 | (concat publish-resolve (match-string 2 url))))) 53 | 54 | ;; this doesn't handle anchors properly yet. 55 | (defun muse-browse-url-iw (url) 56 | (when (string-match "\\`iw:\\([a-zA-Z]*\\)\\\\\\(.+\\)#?\\(.*\\)" url) 57 | (let* ((wiki-resolve 58 | (assoc (match-string 1 url) 59 | muse-interwiki-protocol-alist)) 60 | (browse-resolve 61 | (or (nth 2 wiki-resolve) 62 | (nth 1 wiki-resolve)))) 63 | (find-file 64 | (concat browse-resolve "/" 65 | (match-string 2 url) 66 | ".muse"))))) 67 | 68 | 69 | (provide 'muse-protocol-iw) 70 | ;; muse-protocol-iw.el ends here 71 | -------------------------------------------------------------------------------- /examples/mwolson/templates/header.html: -------------------------------------------------------------------------------- 1 | 2 | (muse-html-encoding)"?> 3 | 4 | 5 | 6 | <lisp>(concat (car (muse-project)) 7 | " - " 8 | (muse-wiki-publish-pretty-title))</lisp> 9 | 10 | 11 | 12 | 14 | 15 | (muse-style-element :style-sheet muse-publishing-current-style) 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 59 | 60 |

61 | " 62 | style="text-decoration: none;"> 63 | mwolson.org logo 65 | 66 | 68 | (concat (car (muse-project)) " - " 69 | (muse-wiki-publish-pretty-title)) 70 | 71 |

72 | 73 | 74 | -------------------------------------------------------------------------------- /scripts/muse-build.el: -------------------------------------------------------------------------------- 1 | (add-to-list 'load-path "../contrib") 2 | (add-to-list 'load-path "../experimental") 3 | (add-to-list 'load-path "../lisp") 4 | 5 | ;; Avoid interference from VC.el 6 | (setq vc-handled-backends nil) 7 | 8 | (defun muse-elint-files () 9 | (require 'elint) 10 | (elint-initialize) 11 | 12 | (defvar nomessage t) 13 | (load "muse" nil nomessage) 14 | (dolist (dir '("../lisp" "../contrib" "../experimental")) 15 | (dolist (file (directory-files dir nil "\\.el$")) 16 | (setq file (substring file 0 (string-match "\\.el$" file))) 17 | (load file nil nomessage))) 18 | 19 | (add-to-list 'elint-standard-variables 'current-prefix-arg) 20 | (add-to-list 'elint-standard-variables 'command-line-args-left) 21 | (add-to-list 'elint-standard-variables 'buffer-file-coding-system) 22 | (add-to-list 'elint-standard-variables 'save-some-buffers-action-alist) 23 | (add-to-list 'elint-standard-variables 'emacs-major-version) 24 | (add-to-list 'elint-standard-variables 'emacs-minor-version) 25 | (add-to-list 'elint-standard-variables 'emacs-version) 26 | (add-to-list 'elint-standard-variables 'window-system) 27 | (add-to-list 'elint-standard-variables 'muse-mode-abbrev-table) 28 | (dolist (file command-line-args-left) 29 | (find-file file) 30 | (message "Checking %s ..." file) 31 | (elint-current-buffer) 32 | (with-current-buffer (elint-get-log-buffer) 33 | (goto-char (point-min)) 34 | (forward-line 2) 35 | (while (not (or (eobp) 36 | (looking-at "^Linting complete"))) 37 | (message (buffer-substring (muse-line-beginning-position) 38 | (muse-line-end-position))) 39 | (forward-line 1))) 40 | (kill-buffer (current-buffer)))) 41 | 42 | (defun muse-generate-autoloads () 43 | (interactive) 44 | (defvar autoload-package-name) 45 | (defvar command-line-args-left) 46 | (defvar generated-autoload-file) 47 | (require 'autoload) 48 | (setq backup-inhibited t) 49 | (setq generated-autoload-file (expand-file-name "muse-autoloads.el")) 50 | (setq command-line-args-left (mapcar #'expand-file-name 51 | command-line-args-left)) 52 | (if (featurep 'xemacs) 53 | (progn 54 | (setq autoload-package-name "muse") 55 | (batch-update-autoloads)) 56 | (find-file generated-autoload-file) 57 | (delete-region (point-min) (point-max)) 58 | (insert ";;; muse-autoloads.el --- autoloads for Muse 59 | ;; 60 | ;;; Code: 61 | ") 62 | (save-buffer 0) 63 | (batch-update-autoloads) 64 | (find-file generated-autoload-file) 65 | (goto-char (point-max)) 66 | (insert ?\n) 67 | (insert "(provide 'muse-autoloads) 68 | ;;; muse-autoloads.el ends here 69 | ;; 70 | ;; Local Variables: 71 | ;; version-control: never 72 | ;; no-byte-compile: t 73 | ;; no-update-autoloads: t 74 | ;; End: 75 | ") 76 | (insert ?\n) 77 | (save-buffer 0) 78 | (kill-buffer (current-buffer)))) 79 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all lisp contrib autoloads examples experimental doc info-only 2 | .PHONY: clean realclean distclean fullclean install-info install-bin install 3 | .PHONY: test dist release upload elpa 4 | 5 | DEFS = $(shell test -f Makefile.defs && echo Makefile.defs \ 6 | || echo Makefile.defs.default) 7 | 8 | include $(DEFS) 9 | 10 | SUBDIRS = lisp contrib examples experimental texi 11 | 12 | all: autoloads lisp contrib info-only 13 | 14 | lisp: 15 | (cd lisp && $(MAKE)) 16 | 17 | contrib: 18 | (cd contrib && $(MAKE)) 19 | 20 | autoloads: 21 | (cd lisp && $(MAKE) autoloads) 22 | 23 | examples: 24 | (cd examples && $(MAKE)) 25 | 26 | experimental: 27 | (cd experimental && $(MAKE)) 28 | 29 | info-only: 30 | (cd texi && $(MAKE) info-only) 31 | 32 | doc texi: 33 | (cd texi && $(MAKE)) 34 | 35 | clean: 36 | for i in $(SUBDIRS); do \ 37 | (cd $$i && $(MAKE) clean); done 38 | 39 | realclean fullclean: clean 40 | for i in $(SUBDIRS); do \ 41 | (cd $$i && $(MAKE) realclean); done 42 | 43 | install-info: 44 | (cd texi && $(MAKE) install) 45 | 46 | install-bin: autoloads lisp contrib 47 | (cd lisp && $(MAKE) install) 48 | (cd contrib && $(MAKE) install) 49 | (cd experimental && $(MAKE) install-uncompiled) 50 | 51 | install: install-bin install-info 52 | 53 | test: 54 | (cd lisp && $(MAKE) test) 55 | 56 | distclean: 57 | for i in $(SUBDIRS); do \ 58 | (cd $$i && $(MAKE) distclean); done 59 | -rm -fr ../$(PROJECT)-$(VERSION) 60 | 61 | dist: autoloads distclean 62 | git archive --format=tar --prefix=$(PROJECT)-$(VERSION)/ HEAD | \ 63 | (cd .. && tar xf -) 64 | rm -f ../$(PROJECT)-$(VERSION)/.gitignore 65 | cp lisp/$(PROJECT)-autoloads.el ../$(PROJECT)-$(VERSION)/lisp 66 | 67 | release: dist 68 | (cd .. && tar -czf $(PROJECT)-$(VERSION).tar.gz \ 69 | $(PROJECT)-$(VERSION) ; \ 70 | zip -r $(PROJECT)-$(VERSION).zip $(PROJECT)-$(VERSION) && \ 71 | gpg --detach $(PROJECT)-$(VERSION).tar.gz && \ 72 | gpg --detach $(PROJECT)-$(VERSION).zip) 73 | 74 | upload: 75 | (cd .. && \ 76 | scp $(PROJECT)-$(VERSION).zip* $(PROJECT)-$(VERSION).tar.gz* \ 77 | mwolson@download.gna.org:/upload/muse-el) 78 | 79 | elpa: realclean info-only 80 | rm -fR $(ELPADIR)/$(PROJECT)-$(VERSION) 81 | rm -f $(ELPADIR)/$(PROJECT)-$(VERSION).tar 82 | mkdir -p $(ELPADIR)/$(PROJECT)-$(VERSION) 83 | cp lisp/*.el $(ELPADIR)/$(PROJECT)-$(VERSION) 84 | cp contrib/*.el $(ELPADIR)/$(PROJECT)-$(VERSION) 85 | echo '(define-package "$(PROJECT)" "$(VERSION)"' > \ 86 | $(ELPADIR)/$(PROJECT)-$(VERSION)/$(PROJECT)-pkg.el 87 | echo ' "$(ELPADESC)")' >> \ 88 | $(ELPADIR)/$(PROJECT)-$(VERSION)/$(PROJECT)-pkg.el 89 | cp texi/$(MANUAL).info $(ELPADIR)/$(PROJECT)-$(VERSION) 90 | cp texi/dir-template $(ELPADIR)/$(PROJECT)-$(VERSION)/dir 91 | install-info --section "Emacs" "Emacs" \ 92 | --info-dir=$(ELPADIR)/$(PROJECT)-$(VERSION) \ 93 | $(ELPADIR)/$(PROJECT)-$(VERSION)/$(MANUAL).info 94 | rm -f $(ELPADIR)/$(PROJECT)-$(VERSION)/dir.old 95 | (cd $(ELPADIR) && tar cf $(PROJECT)-$(VERSION).tar \ 96 | $(PROJECT)-$(VERSION)) 97 | -------------------------------------------------------------------------------- /lisp/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all lisp autoloads clean realclean distclean fullclean install test 2 | .PRECIOUS: %.elc 3 | 4 | DEFS = $(shell test -f ../Makefile.defs && echo ../Makefile.defs \ 5 | || echo ../Makefile.defs.default) 6 | 7 | include $(DEFS) 8 | 9 | EL = $(filter-out $(PROJECT)-autoloads.el,$(wildcard *.el)) 10 | ELC = $(patsubst %.el,%.elc,$(EL)) 11 | 12 | all: lisp 13 | 14 | lisp: autoloads $(ELC) 15 | 16 | $(PROJECT)-build.elc: ../scripts/$(PROJECT)-build.el 17 | @echo $(PROJECT)-build.el is not byte-compiled 18 | 19 | autoloads: $(PROJECT)-autoloads.el 20 | 21 | $(PROJECT)-autoloads.el: $(EL) 22 | @$(EMACS) -q $(SITEFLAG) -batch -l ../scripts/$(PROJECT)-build.el \ 23 | -f $(PROJECT)-generate-autoloads . ../contrib ../experimental 24 | 25 | %.elc: %.el 26 | @$(EMACS) -q $(SITEFLAG) -batch -l ../scripts/$(PROJECT)-build.el \ 27 | -f batch-byte-compile $< 28 | 29 | clean distclean: 30 | -rm -f *.elc *~ 31 | 32 | realclean fullclean: clean 33 | -rm -f $(PROJECT)-autoloads.el 34 | 35 | install: autoloads $(ELC) 36 | install -d $(ELISPDIR) 37 | install -m 0644 $(PROJECT)-autoloads.el $(EL) $(ELC) $(ELISPDIR) 38 | 39 | test: $(ELC) 40 | $(EMACS) -q $(SITEFLAG) -batch -l ../scripts/$(PROJECT)-build.el \ 41 | -f $(PROJECT)-elint-files $(EL) 42 | 43 | # Dependencies 44 | # 45 | # This allows us to recompile Muse safely after an update. 46 | 47 | muse-backlink.elc: muse-mode.elc muse-publish.elc muse.elc 48 | 49 | muse-blosxom.elc: muse-html.elc muse-project.elc muse-publish.elc 50 | 51 | muse-book.elc: muse-latex.elc muse-project.elc muse-publish.elc 52 | muse-book.elc: muse-regexps.elc 53 | 54 | muse-colors.elc: muse-mode.elc muse-regexps.elc 55 | 56 | muse-context.elc: muse-publish.elc 57 | 58 | muse-docbook.elc: muse-publish.elc muse-regexps.elc muse-xml-common.elc 59 | 60 | muse-groff.elc: muse-publish.elc 61 | 62 | muse-html.elc: muse-publish.elc muse-regexps.elc muse-xml-common.elc 63 | 64 | muse-http.elc: muse-html.elc muse-project.elc 65 | 66 | muse-ikiwiki.elc: muse-html.elc muse-ipc.elc muse-publish.elc muse.elc 67 | 68 | muse-import-docbook.elc: muse-import-xml.elc 69 | 70 | muse-import-latex.elc: muse-regexps.elc muse.elc 71 | 72 | muse-ipc.elc: muse-publish.elc muse.elc 73 | 74 | muse-journal.elc: muse-book.elc muse-html.elc muse-latex.elc 75 | muse-journal.elc: muse-publish.elc 76 | 77 | muse-latex.elc: muse-publish.elc 78 | 79 | muse-latex2png.elc: muse-publish.elc 80 | 81 | muse-mode.elc: muse-regexps.elc muse-project.elc 82 | 83 | muse-poem.elc: muse-latex.elc muse-project.elc 84 | 85 | muse-project.elc: muse-publish.elc muse.elc 86 | 87 | muse-protocols.elc: muse-regexps.elc 88 | 89 | muse-publish.elc: muse-regexps.elc muse.elc 90 | 91 | muse-texinfo.elc: muse-latex.elc muse-publish.elc 92 | 93 | muse-wiki.elc: muse-colors.elc muse-regexps.elc muse-mode.elc 94 | 95 | muse-xml-common.elc: muse-publish.elc muse-regexps.elc 96 | 97 | muse-xml.elc: muse-publish.elc muse-regexps.elc muse-xml-common.elc 98 | 99 | muse.elc: muse-protocols.elc muse-regexps.elc 100 | -------------------------------------------------------------------------------- /lisp/muse-import-xml.el: -------------------------------------------------------------------------------- 1 | ;;; muse-import-xml.el --- common to all from-xml converters 2 | 3 | ;; Copyright (C) 2006, 2007, 2008, 2009, 2010 4 | ;; Free Software Foundation, Inc. 5 | 6 | ;; Author: Elena Pomohaci 7 | 8 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 9 | 10 | ;; Emacs Muse is free software; you can redistribute it and/or modify 11 | ;; it under the terms of the GNU General Public License as published 12 | ;; by the Free Software Foundation; either version 3, or (at your 13 | ;; option) any later version. 14 | 15 | ;; Emacs Muse is distributed in the hope that it will be useful, but 16 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | ;; General Public License for more details. 19 | 20 | ;; You should have received a copy of the GNU General Public License 21 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 22 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23 | ;; Boston, MA 02110-1301, USA. 24 | 25 | ;;; Commentary: 26 | 27 | ;;; Contributors: 28 | 29 | ;;; Code: 30 | 31 | (provide 'muse-import-xml) 32 | 33 | (require 'xml) 34 | (require 'muse) 35 | 36 | (defvar muse-import-xml-prefix "" 37 | "The name prefix for tag functions") 38 | 39 | (defvar muse-import-xml-generic-function-name "muse-import-xml-generic" 40 | "The generic function name") 41 | 42 | (defun muse-import-xml-convert-to-list (buf) 43 | "Convert xml BUF in a xml-list" 44 | (with-temp-buffer 45 | (insert-buffer-substring buf) 46 | (goto-char (point-min)) 47 | (while (re-search-forward ">[ \n\t]*<" nil t) 48 | (replace-match "><" nil nil)) ; clean all superfluous blank characters 49 | (xml-parse-region (point-min) 50 | (point-max) 51 | (current-buffer)))) 52 | 53 | 54 | (defun muse-import-xml-generic (node) 55 | "The generic function called when there is no node specific function." 56 | (let ((name (xml-node-name node))) 57 | (insert "<" (symbol-name name) ">") 58 | (muse-import-xml-node node) 59 | (insert ""))) 60 | 61 | (defun muse-import-xml-parse-tree (lst) 62 | "Parse an xml tree list" 63 | (mapc #'muse-import-xml-parse-node lst)) 64 | 65 | (defun muse-import-xml-parse-node (node) 66 | "Parse a xml tree node" 67 | (if (stringp node) 68 | (insert (muse-replace-regexp-in-string "^[ \t]+" "" node)) 69 | (let ((fname (intern-soft (concat muse-import-xml-prefix 70 | (symbol-name (xml-node-name node)))))) 71 | (if (functionp fname) 72 | (funcall fname node) 73 | (funcall (intern muse-import-xml-generic-function-name) node))))) 74 | 75 | 76 | (defun muse-import-xml-node (node) 77 | "Default node function" 78 | (muse-import-xml-parse-tree (xml-node-children node))) 79 | 80 | 81 | (defun muse-import-xml (src dest) 82 | "Convert the xml SRC buffer in a muse DEST buffer" 83 | (set-buffer (get-buffer-create dest)) 84 | (when (fboundp 'muse-mode) 85 | (muse-mode)) 86 | (muse-import-xml-parse-tree (muse-import-xml-convert-to-list src))) 87 | 88 | ;;; muse-import-xml.el ends here 89 | -------------------------------------------------------------------------------- /examples/ikiwiki/muse-init-project.el: -------------------------------------------------------------------------------- 1 | ;;; muse-init-project.el --- Use Emacs Muse to publish ikiwiki documents 2 | 3 | ;; The code in this file may be used, distributed, and modified 4 | ;; without restriction. 5 | 6 | ;;; Setup 7 | 8 | (add-to-list 'load-path (expand-file-name "~ikiwiki/elisp/muse/lisp")) 9 | 10 | ;; Initialize 11 | (require 'muse) ; load generic module 12 | (require 'muse-html) ; load (X)HTML publishing style 13 | (require 'muse-ikiwiki) ; load Ikiwiki integration 14 | (require 'muse-project) ; load support for projects 15 | (require 'muse-wiki) ; load Wiki support 16 | 17 | ;;; Settings 18 | 19 | ;; New variables 20 | (defvar muse-ikiwiki-project "HCoopWiki" 21 | "Name of the project to publish using ikiwiki.") 22 | (defvar muse-ikiwiki-source "/afs/hcoop.net/common/ikiwiki/repo" 23 | "Source directory for Muse files.") 24 | (defvar muse-ikiwiki-dest "/afs/hcoop.net/common/ikiwiki/dest" 25 | "Destination directory for published files.") 26 | 27 | ;; Project listing 28 | (setq muse-project-alist 29 | `((,muse-ikiwiki-project 30 | (,@(muse-project-alist-dirs muse-ikiwiki-source)) 31 | ;; Publish this directory and its subdirectories. Arguments 32 | ;; are as follows. The above `muse-project-alist-dirs' part 33 | ;; is also needed. 34 | ;; 1. Source directory 35 | ;; 2. Output directory 36 | ;; 3. Publishing style 37 | ;; remainder: Other things to put in every generated style 38 | ,@(muse-project-alist-styles muse-ikiwiki-source 39 | muse-ikiwiki-dest 40 | "ikiwiki")))) 41 | 42 | ;; Wiki settings 43 | (setq muse-wiki-allow-nonexistent-wikiword t 44 | muse-wiki-match-all-project-files t 45 | muse-wiki-interwiki-delimiter "::") 46 | (add-to-list 'muse-publish-desc-transforms 'muse-wiki-publish-pretty-interwiki) 47 | (add-to-list 'muse-publish-desc-transforms 'muse-wiki-publish-pretty-title) 48 | (setq muse-wiki-interwiki-alist 49 | '(("EmacsWiki" . "http://www.emacswiki.org/cgi-bin/wiki/") 50 | ("UbuntuLinux" . "http://ubuntulinux.org/"))) 51 | 52 | ;; Permitted modes for to colorize 53 | (setq muse-html-src-allowed-modes 54 | '("ada" "apache" "asm" "awk" "c++" "c" "cc" "change-log" "context" 55 | "css" "diary" "diff" "dns" "domtool" "emacs-lisp" "f90" "fortran" 56 | "fundamental" "html" "java" "jython" "latex" "lisp" "lua" "m4" 57 | "makefile" "markdown" "matlab" "maxima" "message" "modula-2" "muse" 58 | "nroff" "octave" "org" "outline" "pascal" "perl" "ps" "python" "rst" 59 | "ruby" "scheme" "sgml" "sh" "slang" "sml" "sml-cm" "sml-lex" "sml-yacc" 60 | "sql" "tcl" "tex" "texinfo" "xml" "zone")) 61 | ;; In case someone does 62 | (setq muse-colors-evaluate-lisp-tags nil 63 | muse-colors-inline-images nil) 64 | ;; In case someone does 65 | (require 'org) 66 | (setq org-inhibit-startup t 67 | org-table-formula-evaluate-inline nil) 68 | 69 | ;; Don't allow dangerous tags to be published 70 | (setq muse-publish-enable-dangerous-tags nil) 71 | 72 | ;;; Custom variables 73 | 74 | (custom-set-variables 75 | '(muse-html-charset-default "utf-8") 76 | '(muse-html-encoding-default (quote utf-8)) 77 | '(muse-html-meta-content-encoding (quote utf-8)) 78 | '(muse-publish-comments-p t) 79 | '(muse-publish-date-format "%b. %e, %Y")) 80 | (custom-set-faces 81 | '(muse-bad-link ((t (:foreground "DeepPink" :underline "DeepPink" :weight bold))))) 82 | 83 | ;;; muse-init-project.el ends here 84 | -------------------------------------------------------------------------------- /contrib/pyblosxom/getstamps.py: -------------------------------------------------------------------------------- 1 | """ 2 | Run 'python getstamps.py' from the directory that contains your 3 | unpublished blog entries. 4 | 5 | You may need to make some modification for your situation. This 6 | assumes your blog entries use a .txt extension and that you generate 7 | them from "source" files in a different directory (with an optional 8 | .muse extension). 9 | 10 | History: 11 | 12 | 1.1 13 | 14 | * Michael Olson adapted this for Emacs Muse 15 | and added a few more exluded patterns for other version control 16 | systems. 17 | 18 | 1.0 19 | 20 | * Original version 21 | 22 | License: 23 | 24 | Copyright (c) 2006 Nathan Kent Bullock 25 | Copyright (c) 2006, 2007, 2008, 2009, 2010 Michael Olson 26 | 27 | Permission is hereby granted, free of charge, to any person obtaining 28 | a copy of this software and associated documentation files (the 29 | "Software"), to deal in the Software without restriction, including 30 | without limitation the rights to use, copy, modify, merge, publish, 31 | distribute, sublicense, and/or sell copies of the Software, and to 32 | permit persons to whom the Software is furnished to do so, subject to 33 | the following conditions: 34 | 35 | The above copyright notice and this permission notice shall be 36 | included in all copies or substantial portions of the Software. 37 | 38 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 39 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 40 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 41 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 42 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 43 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 44 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 45 | SOFTWARE. 46 | """ 47 | __author__ = 'Nathan Kent Bullock' 48 | __homepage__ = 'http://bullock.moo.com/nathan/' 49 | __email__ = 'nathan_kent_bullock -at- yahoo.ca' 50 | __version__ = '1.1' 51 | 52 | import re, sys, os, types 53 | 54 | OutFile=None 55 | 56 | # The format of the date line in each blog entry 57 | DateRegexp = re.compile (r'^#date\s+(.+)$') 58 | 59 | # The part of the filename of the blog entry to write to the 60 | # timestamps file. Only the first grouping will be used. 61 | FileNameRegexp = re.compile (r'^(.+?)(\.muse)?$') 62 | 63 | def getdate(f): 64 | for line in f: 65 | matched = DateRegexp.search(line) 66 | if matched: 67 | return matched.group(1) 68 | 69 | def recurse(so_far): 70 | global OutFile 71 | 72 | for filename in os.listdir(so_far): 73 | filepath = so_far + "/" + filename 74 | 75 | # just makes output prettier. 76 | if filename == ".svn": continue 77 | if filename == ".arch-ids": continue 78 | if filename == "{arch}": continue 79 | if filename == ".bzr": continue 80 | if filename == "_darcs": continue 81 | 82 | if os.path.isdir(filepath): 83 | print "dir %s" % (filepath,) 84 | recurse(filepath) 85 | 86 | # You may need to modify the extension test 87 | if os.path.isfile(filepath) and filepath != "timestamps": 88 | thisfile = open(filepath,'r') 89 | thisdate = getdate (thisfile) 90 | matched = FileNameRegexp.search(filepath[2:]) 91 | if thisdate and matched: 92 | thisname = matched.group(1) + ".txt" 93 | OutFile.write("%s %s\n" % (thisdate, thisname)) 94 | continue 95 | 96 | if __name__ == "__main__": 97 | OutFile = open("timestamps", "w+") 98 | recurse(".") 99 | -------------------------------------------------------------------------------- /examples/mwolson/stylesheets/blog.css: -------------------------------------------------------------------------------- 1 | /* Michael Olson's tweaked pyblosxom stylesheet 2 | 3 | Elements for my blog. 4 | 5 | License: Modification and propagation of this document is 6 | permitted. Attribution of credit to me is optional. 7 | */ 8 | 9 | td { 10 | } 11 | 12 | th { 13 | } 14 | 15 | li.spaced { 16 | } 17 | 18 | .update { 19 | color: #ff0000; 20 | font-weight: bold; 21 | } 22 | 23 | .header { 24 | font-size: 9pt; 25 | text-align: center; 26 | font-weight: bold; 27 | } 28 | 29 | .data { 30 | font-size: 9pt; 31 | } 32 | 33 | .keyword { 34 | color: #0000ff; 35 | font-weight: bold; 36 | } 37 | .number { 38 | color: #ff00ff; 39 | } 40 | .string { 41 | color: #ff0000; 42 | } 43 | .comment { 44 | color: #000088; 45 | } 46 | .symbol { 47 | } 48 | .normal { 49 | } 50 | .function { 51 | font-weight: bold; 52 | } 53 | 54 | .input { 55 | color: #0000ff; 56 | } 57 | 58 | .code { 59 | font-family: monospace; 60 | font-size: 0.9em; 61 | } 62 | 63 | .path { 64 | font-family: monospace; 65 | font-size: 0.9em; 66 | } 67 | 68 | .rightMenu { 69 | font-size: 10pt; 70 | font-weight: bold; 71 | color: black; /*#336699;*/ 72 | } 73 | 74 | /* Blosxom registry stuff */ 75 | 76 | .blosxomRegistryHeader { 77 | border: 1px solid #999; 78 | margin: 0px; 79 | padding: 0px; 80 | font-weight: bold; 81 | } 82 | 83 | /* Blosxom calendar stuff */ 84 | 85 | .blosxomCalendar { 86 | border: 1px solid #999; 87 | margin: 0px; 88 | padding: 0px; 89 | } 90 | .blosxomCalendarBlogged { 91 | background: #bbbbff; 92 | text-align: center; 93 | color: #000000; 94 | } 95 | .blosxomCalendarCell { 96 | background: #ddddff; 97 | text-align: center; 98 | color: #000000; 99 | } 100 | .blosxomCalendarToday { 101 | background: #ffffcc; 102 | color: #000000; 103 | } 104 | .blosxomCalendarSpecificDay { 105 | background: #ffffcc; 106 | text-align: center; 107 | color: #000000; 108 | } 109 | 110 | /* Blosxom stuff */ 111 | 112 | .blosxomDayDiv { 113 | float: left; 114 | width: 100%; 115 | } 116 | 117 | .blosxomEntry { 118 | width: 100%; 119 | margin-top: 1em; 120 | margin-bottom: 2em; 121 | padding: 0; 122 | } 123 | 124 | .blosxomEntrySummary { 125 | width: 100%; 126 | /* margin-top: 1em; */ 127 | /* margin-bottom: 2em; */ 128 | padding: 0; 129 | } 130 | 131 | .blosxomBody { 132 | padding-left: 1em; 133 | padding-right: 1em; 134 | } 135 | 136 | .blosxomStoryLinks { 137 | /* background: #eeeeee; */ 138 | /* text-align: right; */ 139 | } 140 | 141 | .blosxomComments { 142 | margin-top: 2em; 143 | border-top: 1px dashed #444444; 144 | } 145 | 146 | .blosxomCommentForm { 147 | clear: right; 148 | } 149 | 150 | .blosxomTitle { 151 | /* font-size: 13pt; */ 152 | font-weight: bold; 153 | color: #000000; 154 | } 155 | .blosxomDate { 156 | border-bottom: 1px solid #888888; 157 | font-size: 11pt; 158 | font-weight: bold; 159 | color: #336699; 160 | } 161 | 162 | .blosxomEntryDate { 163 | font-weight: bold; 164 | font-size: 100%; 165 | color: #aaaaaa; 166 | } 167 | 168 | .blosxomTime { 169 | text-decoration: italicize; 170 | color: #336699; 171 | } 172 | 173 | /* Blosxom comment stuff */ 174 | 175 | .blosxomComment { 176 | background: #eeeeee; 177 | border-top: dashed 1px #444444; 178 | padding: 0.2em; 179 | padding-bottom: 1em; 180 | } 181 | 182 | .blosxomCommentInfo { 183 | font-size: smaller; 184 | } 185 | 186 | .blosxomCommentBody { 187 | margin-left: 0.5em; 188 | } 189 | 190 | .blosxomCommentForm { 191 | margin-top: 1em; 192 | } 193 | 194 | #blosxomCommentStatus { 195 | font-size: larger; 196 | color: blue; 197 | margin-left: 0.5em; 198 | font-weight: bold; 199 | } 200 | -------------------------------------------------------------------------------- /contrib/pyblosxom/hardcodedates.py: -------------------------------------------------------------------------------- 1 | """ 2 | This allows the user to create a file "timestamps" in their top-level 3 | blog entries directory, that will override the timestamp of any given 4 | blog entry. 5 | 6 | Each line in this file should be in one of the following forms. 7 | 8 | "YYYY-MM-DD-hh-mm file-name" 9 | "YYYY-MM-DD file-name" 10 | 11 | Then for any entry that one of these lines exist the system will use 12 | that timestamp instead of the actual files modification time. 13 | 14 | Note: the filename is relative to your data-dir. An example follows 15 | of a line for the file /var/data-dir/school/abc.txt, where the 16 | top-level blog entries directory is "/var/data-dir/" and the date is 17 | Aug 9, 2004. 18 | 19 | 2004-08-09-00-00 school/abc.txt 20 | 21 | History: 22 | 23 | 1.3 24 | 25 | * Michael Olson made it optional to include 26 | the hours and minutes. 27 | 28 | 1.2 29 | 30 | * Original version 31 | 32 | License: 33 | 34 | Copyright (c) 2006 Nathan Kent Bullock 35 | Copyright (c) 2006, 2007, 2008, 2009, 2010 Michael Olson 36 | 37 | Permission is hereby granted, free of charge, to any person obtaining 38 | a copy of this software and associated documentation files (the 39 | "Software"), to deal in the Software without restriction, including 40 | without limitation the rights to use, copy, modify, merge, publish, 41 | distribute, sublicense, and/or sell copies of the Software, and to 42 | permit persons to whom the Software is furnished to do so, subject to 43 | the following conditions: 44 | 45 | The above copyright notice and this permission notice shall be 46 | included in all copies or substantial portions of the Software. 47 | 48 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 49 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 50 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 51 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 52 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 53 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 54 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 55 | SOFTWARE. 56 | """ 57 | __author__ = 'Nathan Kent Bullock' 58 | __homepage__ = 'http://bullock.moo.com/nathan/' 59 | __email__ = 'nathan_kent_bullock -at- yahoo.ca' 60 | __version__ = '1.3' 61 | 62 | from Pyblosxom import tools 63 | import os, re, time, sys 64 | 65 | FILETIME = re.compile('^([0-9]{4})-([0-1][0-9])-([0-3][0-9])(-([0-2][0-9])-([0-5][0-9]))? +(.*)$') 66 | 67 | all_timestamps = None 68 | 69 | def get_all_timestamps(datadir): 70 | f = open(datadir + "/timestamps") 71 | t = [] 72 | while True: 73 | str = f.readline() 74 | if str == "": break 75 | m = FILETIME.search(str.strip()) 76 | if m: 77 | year = int(m.group(1)) 78 | mo = int(m.group(2)) 79 | day = int(m.group(3)) 80 | if m.group(4): 81 | hr = int(m.group(5)) 82 | minute = int(m.group(6)) 83 | else: 84 | hr = 0 85 | minute = 0 86 | mtime = time.mktime((year,mo,day,hr,minute,0,0,0,-1)) 87 | 88 | t.append( (datadir + "/" + m.group(7), mtime) ) 89 | 90 | f.close() 91 | return t 92 | 93 | def cb_filestat(args): 94 | global all_timestamps 95 | 96 | filename = args["filename"] 97 | stattuple = args["mtime"] 98 | 99 | for fname,mtime in all_timestamps: 100 | if fname == filename: 101 | args["mtime"] = tuple(list(stattuple[:8]) + [mtime] + list(stattuple[9:])) 102 | break 103 | 104 | return args 105 | 106 | def cb_start(args): 107 | global all_timestamps 108 | all_timestamps = get_all_timestamps(args["request"].getConfiguration()['datadir']) 109 | -------------------------------------------------------------------------------- /contrib/pyblosxom/metadate.py: -------------------------------------------------------------------------------- 1 | """ 2 | Purpose: 3 | 4 | If an entry contains a #postdate metatag, metadate.py makes 5 | pyblosxom use that as the entry's date instead of the file's mtime. 6 | 7 | To use: 8 | 9 | Place this file in your pyblosxom plugins directory. 10 | 11 | If you have previously assigned a value to py['load_plugins'] in 12 | your config.py file, add this module to that list. 13 | 14 | Tag an entry with a metadata line like so: 15 | #postdate YYYY-MM-DD HH-MM 16 | 17 | Developer Info: 18 | 19 | There really isn't a clean way to implement this (as far as I can 20 | tell). The cb_filestat callback isn't passed the entry, and none of 21 | the other callbacks are passed the mtime, and we really need them 22 | both to do this properly. 23 | 24 | The ugly--but functional--solution to this problem is to go into the 25 | file and dig the metadata out directly. That is what I have done 26 | here. 27 | 28 | Since the entries are now being opened twice each, this could result 29 | in decently-sized (relatively speaking) performance hit. Consider 30 | yourself warned. 31 | 32 | License: 33 | 34 | Permission is hereby granted, free of charge, to any person 35 | obtaining a copy of this software and associated documentation files 36 | (the"Software"), to deal in the Software without restriction, 37 | including without limitation the rights to use, copy, modify, merge, 38 | publish, distribute, sublicense, and/or sell copies of the Software, 39 | and to permit persons to whom the Software is furnished to do so, 40 | subject to the following conditions: 41 | 42 | The above copyright notice and this permission notice shall be 43 | included in all copies or substantial portions of the Software. 44 | 45 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 46 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 47 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 48 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 49 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 50 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 51 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 52 | SOFTWARE. 53 | 54 | Copyright 2005 Cameron Desautels 55 | """ 56 | 57 | import os, re, time 58 | 59 | __author__ = 'Cameron Desautels ' 60 | __version__ = 'metadate.py, v 0.1' 61 | __description__ = 'Implements overriding of mtime with #postdate metadata.' 62 | 63 | DATEFORMAT = re.compile('([0-9]{4})-([0-1][0-9])-([0-3][0-9]) ([0-2][0-9]):([0-5][0-9])') 64 | 65 | def cb_filestat(args): 66 | stattuple = args['mtime'] 67 | 68 | try: 69 | story = open(args['filename']).readlines() 70 | except IOError: 71 | raise IOError 72 | 73 | if story: 74 | story.pop(0) #throw away the title 75 | 76 | while story: 77 | metamatch = re.match(r'#(\w+)\s+(.*)', story[0]) 78 | if metamatch: 79 | if metamatch.groups()[0] == 'postdate': 80 | datematch = DATEFORMAT.match(metamatch.groups()[1].strip()) 81 | if datematch: 82 | # year, month, day, hour, minute 83 | mtime = time.mktime((int(datematch.groups()[0]),int(datematch.groups()[1]), \ 84 | int(datematch.groups()[2]),int(datematch.groups()[3]), \ 85 | int(datematch.groups()[4]),0,0,0,-1)) 86 | 87 | args['mtime'] = tuple(list(stattuple[:8]) + [mtime] + list(stattuple[9:])) 88 | 89 | # whether the postdate line was correct or malformed, we found it, so quit 90 | break 91 | else: 92 | # that wasn't the right metadata line, so chuck it and keep going 93 | story.pop(0) 94 | else: 95 | # quit when all metadata has been examined 96 | break 97 | 98 | return args 99 | -------------------------------------------------------------------------------- /etc/IDEAS.muse: -------------------------------------------------------------------------------- 1 | This is the "Ideas" page for Emacs Muse. 2 | 3 | It lists various ideas for future enhancements to Emacs Muse. It also 4 | serves to keep track of various changes that the maintainer would like 5 | to merge into Muse at some point. 6 | 7 | * Pending code 8 | 9 | This is code that may or may not be already approved, but should be 10 | checked out at some point. 11 | 12 | ** Waiting for a new release 13 | 14 | - Jim Ottaway 15 | - jeho-latex.el: a rewrite of muse-latex.el which should replace it 16 | at some point. 17 | - muse-latex-labels.el: addition of cross-references to LaTeX. 18 | Should be merged into muse-latex.el after replacing with 19 | jeho-latex.el. 20 | 21 | - David D. Smith 22 | - dds-emphasis-bits.el 23 | - New syntax for explicitly specifying emphasis: 24 | {[_-=*] some emphasized text}. 25 | Also, {** some text **} and {*** some text ***} should work. 26 | - Using -strike- to do strikethrough. 27 | 28 | * Ideas without code 29 | 30 | ** After 3.10 release 31 | 32 | None of these ideas has been finalized yet. 33 | 34 | *** Support for different source markup formats 35 | 36 | For any of these to be done, we have to write functions that call the 37 | right program to do the publishing for us. If the markup format has 38 | some project-aware tools, write Elisp wrappers for those at the 39 | project-publish level. 40 | 41 | - Markdown: http://daringfireball.net/projects/markdown/ 42 | 43 | mwolson: I hate this format, but it's popular. 44 | 45 | - reStructuredText: http://docutils.sourceforge.net/rst.html 46 | 47 | mwolson: I like this format from an initial glance. 48 | 49 | - AsciiDoc: http://www.methods.co.nz/asciidoc/index.html 50 | 51 | Git uses this, but it has heavy dependencies. 52 | 53 | - Org Mode: http://orgmode.org/ 54 | 55 | Just use org-publish functions. 56 | 57 | - Like Muse's default markup, but allow tags to be specified in 58 | Texinfo style: namely, "@tagname{contents}" instead of 59 | "contents" for small regions and 60 | "@tagname\ncontents\n@end tagname" for large regions. 61 | 62 | This might be a pain to implement, and only one person has asked 63 | for it. 64 | 65 | - Take markup features from phpBB and make a format out of it. This 66 | could interest the forum crowd in our work. 67 | 68 | mwolson: I do not have interest in making a new markup format at 69 | the moment. 70 | 71 | *** Publishing to plain text 72 | 73 | - The file experimental/muse-message.el also needs some attention, so 74 | that it can do plain text. Maybe it should be renamed to 75 | muse-plain-text.el. 76 | 77 | - People have requested being able to publish Muse format to other 78 | stuff like rst and markdown. 79 | 80 | mwolson: I'm not in any hurry to implement this. 81 | 82 | *** Make tags for every "main" Muse markup syntax 83 | 84 | The idea is to have something to fall back on. One use case is 85 | putting a list into a table. 86 | 87 | *** Allow pages made by M-x muse-index to be refreshed automatically 88 | 89 | The idea is to update the contents of the index page whenever a new 90 | page is saved. This should be controlled by a new customizable option 91 | called `muse-index-update', which is either nil or non-nil. 92 | 93 | `muse-index' should be modified to add the generated buffer into a new 94 | variable called `muse-index-buffers'. 95 | 96 | A new function called `muse-index-update-buffers' should be made, 97 | which goes through the list `muse-index-buffers', doing the following. 98 | It must check `muse-index-update' first to see whether it should do 99 | anything. It must take no arguments. 100 | 101 | (let ((index (muse-index-as-string as-list exclude-private))) 102 | (dolist (buffer muse-index-buffers) 103 | (with-current-buffer buffer 104 | (erase-buffer) 105 | (insert index) 106 | (current-buffer)))) 107 | 108 | This function should be added to after-save-hook in muse-mode.el. 109 | -------------------------------------------------------------------------------- /examples/mwolson/templates/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /lisp/muse-import-docbook.el: -------------------------------------------------------------------------------- 1 | ;;; muse-import-docbook.el --- convert Docbook XML into Muse format 2 | 3 | ;; Copyright (C) 2006, 2007, 2008, 2009, 2010 4 | ;; Free Software Foundation, Inc. 5 | 6 | ;; Author: Elena Pomohaci 7 | 8 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 9 | 10 | ;; Emacs Muse is free software; you can redistribute it and/or modify 11 | ;; it under the terms of the GNU General Public License as published 12 | ;; by the Free Software Foundation; either version 3, or (at your 13 | ;; option) any later version. 14 | 15 | ;; Emacs Muse is distributed in the hope that it will be useful, but 16 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | ;; General Public License for more details. 19 | 20 | ;; You should have received a copy of the GNU General Public License 21 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 22 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23 | ;; Boston, MA 02110-1301, USA. 24 | 25 | ;;; Commentary: 26 | 27 | ;; It works only for article type docbook docs and recognize 28 | ;; followings elements: article, sect1, sect2, sect3, title, 29 | 30 | ;;; Contributors: 31 | 32 | ;;; Code: 33 | 34 | (require 'muse-import-xml) 35 | 36 | (defvar muse-import-docbook-prefix "muse-import-docbook-" 37 | "The name prefix for tag functions") 38 | 39 | (defvar muse-import-docbook-para-indent "\n\n" 40 | "Para elements indentation (0, less than 6 spaces, more than 6 spaces)") 41 | 42 | (defun muse-import-docbook-reset-para-indent () 43 | (setq muse-import-docbook-para-indent "\n\n")) 44 | 45 | 46 | ;;;###autoload 47 | (defun muse-import-docbook (src dest) 48 | "Convert the Docbook buffer SRC to Muse, writing output in the DEST buffer." 49 | (interactive "bDocbook buffer:\nBMuse buffer:") 50 | (setq muse-import-xml-prefix muse-import-docbook-prefix) 51 | (setq muse-import-xml-generic-function-name "muse-import-xml-node") 52 | (muse-import-xml src dest)) 53 | 54 | ;;;###autoload 55 | (defun muse-import-docbook-files (src dest) 56 | "Convert the Docbook file SRC to Muse, writing output to the DEST file." 57 | (interactive "fDocbook file:\nFMuse file:") 58 | (with-temp-file dest 59 | (muse-import-docbook (find-file-noselect src) (current-buffer)))) 60 | 61 | 62 | ;;; element specific functions 63 | 64 | (defun muse-import-docbook-get-title (node) 65 | (let ((tit (car (xml-get-children node 'title)))) 66 | (insert (car (cddr tit)) ?\n ?\n) 67 | (muse-import-xml-parse-tree (xml-node-children (remove tit node))))) 68 | 69 | 70 | (defun muse-import-docbook-article (node) 71 | "Article conversion function" 72 | (muse-import-xml-node node)) 73 | 74 | (defun muse-import-docbook-articleinfo (node) 75 | "Article conversion function" 76 | (insert "#title ") 77 | (muse-import-docbook-get-title node) 78 | (insert ?\n)) 79 | 80 | 81 | (defalias 'muse-import-docbook-appendix 'muse-import-docbook-article) 82 | 83 | (defalias 'muse-import-docbook-appendixinfo 'muse-import-docbook-articleinfo) 84 | 85 | 86 | (defun muse-import-docbook-sect1 (node) 87 | "Section 1 conversion function" 88 | (insert ?\n "* ") 89 | (muse-import-docbook-get-title node)) 90 | 91 | (defun muse-import-docbook-sect2 (node) 92 | "Section 2 conversion function" 93 | (insert ?\n "** ") 94 | (muse-import-docbook-get-title node)) 95 | 96 | (defun muse-import-docbook-sect3 (node) 97 | "Section 3 conversion function" 98 | (insert ?\n "*** ") 99 | (muse-import-docbook-get-title node)) 100 | 101 | 102 | (defun muse-import-docbook-graphic (node) 103 | "Graphic conversion function. Image format is forced to PNG" 104 | (let ((name (xml-get-attribute node 'fileref))) 105 | (insert "\n[[img/" name ".png][" name "]]"))) 106 | 107 | (defun muse-import-docbook-para (node) 108 | (insert muse-import-docbook-para-indent) 109 | (muse-import-xml-node node)) 110 | 111 | 112 | (defun muse-import-docbook-emphasis (node) 113 | (insert "*") 114 | (muse-import-xml-node node) 115 | (insert "*")) 116 | 117 | (defun muse-import-docbook-quote (node) 118 | (insert "\"") 119 | (muse-import-xml-node node) 120 | (insert "\"")) 121 | 122 | (defun muse-import-docbook-blockquote (node) 123 | (setq muse-import-docbook-para-indent "\n\n ") 124 | (muse-import-xml-node node) 125 | (muse-import-docbook-reset-para-indent)) 126 | 127 | (defun muse-import-docbook-member (node) 128 | (insert "\n> ") 129 | (muse-import-xml-node node)) 130 | 131 | (defun muse-import-docbook-bridgehead (node) 132 | (insert "\n* ") 133 | (muse-import-xml-node node)) 134 | 135 | (provide 'muse-import-docbook) 136 | 137 | ;;; muse-import-docbook.el ends here 138 | -------------------------------------------------------------------------------- /experimental/muse-cite.el: -------------------------------------------------------------------------------- 1 | ;;; muse-cite.el --- smart citations for Muse 2 | 3 | ;; Copyright (C) 2005 Free Software Foundation, Inc. 4 | 5 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 6 | 7 | ;; Emacs Muse is free software; you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published 9 | ;; by the Free Software Foundation; either version 3, or (at your 10 | ;; option) any later version. 11 | 12 | ;; Emacs Muse is distributed in the hope that it will be useful, but 13 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | ;; General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 19 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | ;; Boston, MA 02110-1301, USA. 21 | 22 | ;;; Commentary: 23 | 24 | ;; This file is currently in experimental state. I found it in an old 25 | ;; pre-release version of Muse and thought it might come in handy. 26 | 27 | ;;; Contributors: 28 | 29 | ;;; Code: 30 | 31 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 32 | ;; 33 | ;; Muse Smart Citations 34 | ;; 35 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 36 | 37 | ;;; Commentary: 38 | 39 | ;; If a footnote is of the general form "AUTHOR, TITLE, PAGES", this 40 | ;; module offers a function to more intelligently markup such 41 | ;; citations. For LaTeX, it italicizes the TITLE and inserts correct 42 | ;; spacing and endashes in PAGES. For HTML, it is able to convert the 43 | ;; TITLE or PAGES into a link, given knowledge of where to find known 44 | ;; texts by certain authors. 45 | ;; 46 | ;; To use this module -- since it only rewrites markup, and is not 47 | ;; particular to any style -- modify `muse-before-publish-hook': 48 | ;; 49 | ;; (require 'muse-publish) 50 | ;; (require 'muse-cite) 51 | ;; (add-hook 'muse-before-publish-hook 'muse-cite-munge-footnotes) 52 | 53 | (require 'muse-publish) 54 | 55 | (defgroup muse-cite nil 56 | "Offers functionality for marking up smart citations." 57 | :group 'muse-publish) 58 | 59 | (defcustom muse-cite-titles nil 60 | "An alist of authors and the titles they've written. 61 | This is how titles are recognized, and marked up as links to the 62 | title and to the specific pages referenced. 63 | 64 | This variable is an alist of the form: 65 | 66 | ((AUTHOR . TITLE-LIST) 67 | ...) 68 | 69 | Where AUTHOR is a string, and TITLE-LIST is a list of the form: 70 | 71 | ((TITLE URL [PAGE-URL]) 72 | ...) 73 | 74 | Where TITLE is a string, URL is a URL string, and PAGE-URL can be 75 | nil or a URL string with %d somewhere in it -- which is substituted 76 | with the first page number mentioned in the reference." 77 | :type '(alist :key-type (string :tag "Author") 78 | :value-type 79 | (repeat (list (string :tag "Title") 80 | (string :tag "URL") 81 | (choice (string :tag "Page URL") 82 | (const :tag "No Page URL" nil))))) 83 | :group 'muse-cite) 84 | 85 | (defun muse-cite-rewrite (citation) 86 | "Rewrite an 'Author, Title, Pages' CITATION as an intelligent reference." 87 | (when (string-match 88 | (concat "\\([^,]+\\), *\\([^,]+\\), *" 89 | "\\(pp?\\. *\\([0-9]+\\)\\(-+[0-9]+\\)?\\)") citation) 90 | (let* ((author (match-string 1 citation)) 91 | (title (match-string 2 citation)) 92 | (pages (match-string 3 citation)) 93 | (page (match-string 4 citation)) 94 | (author-entry (assoc author muse-cite-titles)) 95 | (book-entry (and author-entry 96 | (assoc title (cdr author-entry)))) 97 | (book-url (car (cdr book-entry))) 98 | (book-page (car (cddr book-entry)))) 99 | (cond 100 | ((null book-url) 101 | (format "%s, *%s*, %s" author title pages)) 102 | ((or (null book-page) 103 | (not (string-match "%d" book-page))) 104 | (format "%s, [[%s][%s]], %s" author book-url title pages)) 105 | (t 106 | (setq book-page (replace-match page nil t book-page)) 107 | (format "%s, [[%s][%s]], [[%s][%s]]" 108 | author book-url title book-page pages)))))) 109 | 110 | (defun muse-cite-munge-footnotes () 111 | "Munge the footnote citations in the current buffer. 112 | The author/title definitions given in `muse-cite-titles' are used 113 | to change the citations automagically into hyperlinks.." 114 | (goto-char (point-max)) 115 | (when (re-search-backward "^Footnotes" nil t) 116 | (while (re-search-forward "^\\[[0-9]+\\][ \t]+\\(.+\\)" nil t) 117 | (let ((end (copy-marker (match-end 0) t)) 118 | (rewrite (save-match-data 119 | (muse-cite-rewrite (match-string 1))))) 120 | (when rewrite 121 | (goto-char (match-beginning 1)) 122 | (delete-region (match-beginning 1) (match-end 1)) 123 | (insert rewrite)) 124 | (goto-char end)))) 125 | nil) 126 | 127 | (provide 'muse-cite) 128 | 129 | ;;; muse-cite.el ends here 130 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Muse 2 | ==== 3 | 4 | This is a listing of those who have made contributions of code or 5 | documentation to Muse. 6 | 7 | John Wiegley: Original author 8 | 9 | Michael Olson: Current maintainer 10 | 11 | Adrian Aichner: Contributor: 12 | - muse-publish.el: 2 lines changes 13 | 14 | Florian Beck: Contributor: 15 | - muse-regexps.el: 1 line changed 16 | 17 | Karl Berry: Contributor: 18 | - muse-latex.el: 5 lines changed 19 | 20 | Jean Magnan de Bornier: Author of muse-context.el, 21 | Contributor 22 | (assigned past and future changes) 23 | 24 | Trent Buck: Contributor: 25 | - muse-latex.el: 4 lines changed 26 | 27 | Sacha Chua: Contributor -- documentation 28 | (assigned past and future changes) 29 | 30 | Brad Collins: Author of: 31 | - muse-protocols.el 32 | - examples/muse.rnc schema 33 | Contributor 34 | (assigned past and future changes) 35 | 36 | Li Daobing: Author of muse-mathml.el, 37 | Contributor 38 | (assigned past and future changes) 39 | 40 | Wang Diancheng: Contributor: 41 | - muse-publish.el: 1 line changed 42 | - muse-regexps.el: 6 lines changed 43 | 44 | Clinton Ebadi: Contributor: 45 | - muse-html.el: 4 lines changed 46 | - muse-latex2png: 3 lines changed 47 | 48 | Bastien Guerry: Contributor 49 | (assigned past and future changes) 50 | 51 | Magnus Henoch: Contributor: 52 | - muse.el: 1 line changed 53 | 54 | Yann Hodique: Author of muse-wiki.el, 55 | Contributor 56 | (assigned past and future changes) 57 | 58 | Markus Hoenicka: Contributor 59 | (assigned past and future changes) 60 | 61 | Andrew J. Korty: Author of muse-groff.el 62 | (assigned past and future changes) 63 | 64 | Sasha Kovar: Contributor 65 | - muse-blosxom.el: >15 lines changed 66 | 67 | Bradley M. Kuhn: Contributor -- documentation 68 | - muse.texi: 9 lines changed 69 | 70 | Peter K. Lee: Contributor 71 | (assigned past and future changes) 72 | 73 | Na Li: Contributor: 74 | - muse-latex2png.el: 1 line changed 75 | 76 | Phillip Lord: Author of: 77 | - muse-split.el 78 | - muse-protocol-iw.el 79 | Contributor 80 | (assigned past and future changes) 81 | 82 | Chris Lowis: Contributor: 83 | - muse-latex2png.el: 1 line changed 84 | 85 | Deus Max: Contributor: 86 | - muse-publish.el: 2 lines changed 87 | 88 | Evan Monroig: Contributor: 89 | - muse.el: 2 lines changed 90 | 91 | Alex Ott: Contributor: 92 | - muse-html.el: 13 lines changed 93 | - muse-publish.el: 2 lines changed 94 | 95 | Jim Ottaway: Author of muse-backlink.el, 96 | Contributor 97 | (assigned past and future changes) 98 | 99 | Elena Pomohaci: Author of: 100 | - muse-import-docbook.el 101 | - muse-import-xml.el 102 | (assigned past and future changes) 103 | 104 | Andrea Riciputi: Idea taken from code, but re-implemented 105 | 106 | Stefan Schlee: Contributor 107 | - muse-mode: >15 lines changed 108 | - muse-protocols.el: 1 line changed 109 | - muse.texi: 7 lines changed 110 | (assigned past and future changes) 111 | 112 | Per B. Sederberg: Contributor 113 | (assigned past and future changes) 114 | 115 | René Stadler: Contributor: 116 | - muse-journal.el: 1 line changed 117 | - muse-project.el: 1 line changed 118 | 119 | Dale P. Smith: Contributor 120 | (disclaimed changes to Emacs) 121 | 122 | John Sullivan: Contributor -- documentation 123 | (assigned past and future changes) 124 | 125 | Ganesh Swami: Original author of latex2png.el, which was the basis for 126 | muse-latex2png.el. It has since been extensively 127 | rewritten, so we no longer need an assignment. 128 | 129 | G. J. Teale: Contributor: 130 | - muse-project.el: 2 lines changed 131 | 132 | Sebastian Tennant: Contributor -- documentation 133 | - muse.texi: 4 lines changed 134 | 135 | Gary Vaughan: Original author of emacs-wiki-blosxom.el, which was the 136 | basis for muse-blosxom.el 137 | (assigned past and future changes) 138 | 139 | Sergey Vlasov: Contributor: 140 | - muse-colors.el: 3 lines changed 141 | 142 | Valery V. Vorotyntsev: Contributor: 143 | - muse-protocols.el: 7 lines changed 144 | 145 | Charles Wang: Contributor: 146 | - muse-html.el: 4 lines changed 147 | (assigned past and future changes) 148 | 149 | Lan Yufeng: Contributor: 150 | - muse-colors.el: 1 line changed 151 | 152 | 153 | Contributed software 154 | ==================== 155 | 156 | This is a listing of authors of software in the `contrib' directory. 157 | 158 | Nathan Kent Bullock: pyblosxom/getstamps.py, pyblosxom/hardcodedates.py 159 | 160 | Cameron Desautels: pyblosxom/metadate.py 161 | 162 | Mark Ivey: blosxom/metadate_0_0_3 163 | 164 | Eric Marsden: cgi.el, httpd.el 165 | (assigned past and future changes to FSF) 166 | 167 | Michael Welle: blosxom/getstamps.pl 168 | -------------------------------------------------------------------------------- /contrib/ikiwiki/IkiWiki/Plugin/muse.pm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # Ikiwiki plugin for Emacs Muse. 3 | # Author: Michael Olson 4 | # License: GPLv2 or later 5 | # 6 | # In your ikiwiki.setup file, set the muse_init option to the location 7 | # of the init file for Muse. Some examples provided in the 8 | # examples/ikiwiki directory are muse-init-simple.el and 9 | # muse-init-project.el. 10 | 11 | package IkiWiki::Plugin::muse; 12 | 13 | use warnings; 14 | use strict; 15 | use IkiWiki 3.00; 16 | 17 | use Date::Format (); 18 | use Encode (); 19 | use File::Temp (); 20 | 21 | sub import { 22 | hook(type => "getsetup", id => "muse", call => \&getsetup); 23 | hook(type => "scan", id => "muse", call => \&scan); 24 | hook(type => "filter", id => "muse", call => \&filter); 25 | hook(type => "htmlize", id => "muse", call => \&htmlize); 26 | } 27 | 28 | sub getsetup () { 29 | return ( 30 | plugin => { 31 | safe => 1, 32 | rebuild => 1, # format plugin 33 | }, 34 | muse_emacs => { 35 | type => "string", 36 | example => "/usr/bin/emacs", 37 | description => "the location of Emacs", 38 | safe => 1, 39 | rebuild => 1, 40 | }, 41 | muse_init => { 42 | type => "string", 43 | example => "~/ikiwiki/muse-init.el", 44 | description => "the location of your Muse init file", 45 | safe => 1, 46 | rebuild => 1, 47 | }, 48 | ); 49 | } 50 | 51 | # Handle Muse directives 52 | sub scan (@) { 53 | my %params=@_; 54 | return unless pagetype($pagesources{$params{page}}) eq 'muse'; 55 | my $canmeta = UNIVERSAL::can('IkiWiki::Plugin::meta', 'preprocess'); 56 | my $cantag = UNIVERSAL::can('IkiWiki::Plugin::tag', 'preprocess_tag'); 57 | return unless $canmeta || $cantag; 58 | my $fun; 59 | 60 | $_ = $params{content}; 61 | pos = undef; 62 | while ( m/ \G \# ([a-zA-Z-]+) \s+ (.+?) \n+ /sgx ) { 63 | my ($key, $val) = ($1, $2); 64 | if ( $key =~ m/^(tags?|category)$/s ) { 65 | next unless $cantag; 66 | $fun = sub { 67 | IkiWiki::Plugin::tag::preprocess_tag( 68 | (map { $_ => '' } (split /\s+/, $val)), 69 | page => $params{page}, 70 | destpage => $params{page}, 71 | preview => 1, 72 | ); 73 | }; 74 | } 75 | else { 76 | next unless $canmeta; 77 | if ( $key eq 'date' ) { 78 | # Support pyblosxom-style dates (YYYY-MM-DD(-hh-mm)?) 79 | my $re = qr/ ^ ([0-9]{4}) - ([0-1][0-9]) - ([0-3][0-9]) 80 | (?: - ([0-2][0-9]) - ([0-5][0-9]) )? $ /sx; 81 | if ( $val =~ m/$re/ ) { 82 | my @array = (0, $5 || 0, $4 || 0, $3, $2, $1 - 1900); 83 | $val = Date::Format::strftime("%a, %e %b %Y %T", @array); 84 | } 85 | } 86 | $fun = sub { 87 | IkiWiki::Plugin::meta::preprocess( 88 | $key, $val, 89 | page => $params{page}, 90 | destpage => $params{page}, 91 | preview => 1, 92 | ); 93 | }; 94 | } 95 | if ( $params{muse_filter} ) { 96 | # Make "wantarray" work in the meta plugin 97 | my $ret = $fun->(); 98 | } 99 | else { 100 | $fun->(); 101 | } 102 | } 103 | } 104 | 105 | # Determine the emacs binary to use 106 | sub locate_emacs { 107 | my $err = sub { 108 | die "Unable to find your emacs binary.\n", 109 | " Set muse_emacs config to the right value.\n"; 110 | }; 111 | if ( $config{muse_emacs} ) { 112 | ( -x $config{muse_emacs} ) ? return $config{muse_emacs} : $err->(); 113 | } 114 | else { 115 | my $emacs = `which emacs`; 116 | chomp $emacs; 117 | ( $emacs ) ? return $emacs : $err->(); 118 | } 119 | } 120 | 121 | # Pass the content of the page to Muse for publishing 122 | sub filter (@) { 123 | my %params=@_; 124 | return $params{content} 125 | unless pagetype($pagesources{$params{page}}) eq 'muse'; 126 | 127 | # Force detection of the Muse #date directive 128 | scan( 129 | content => $params{content}, 130 | page => $params{page}, 131 | muse_filter => 1, 132 | ); 133 | 134 | my $content = Encode::encode_utf8($params{content}); 135 | my $qname = $params{page}; 136 | $qname =~ s/"/\\"/g; 137 | 138 | my ($fh, $filename) = File::Temp::tempfile(); 139 | print $fh $content; 140 | close $fh; 141 | my $qfile = $filename; 142 | $qfile =~ s/"/\\"/g; 143 | eval { 144 | system locate_emacs(), 145 | qw( -q --no-site-file -batch -l ), $config{muse_init}, 146 | '--eval', qq{(muse-ikiwiki-publish-file "$qfile" "$qname")}; 147 | { 148 | open my $ifh, '<', $filename; 149 | local $/; $content = <$ifh>; 150 | close $ifh; 151 | } 152 | unlink $filename; 153 | }; 154 | if ($@) { 155 | my $ret = $@; 156 | unlink $filename; 157 | die $ret; 158 | } 159 | return Encode::decode_utf8($content); 160 | } 161 | 162 | # Fake handler to make publishing work 163 | sub htmlize (@) { 164 | my %params=@_; 165 | return $params{content}; 166 | } 167 | 168 | 1 169 | -------------------------------------------------------------------------------- /experimental/muse-mathml.el: -------------------------------------------------------------------------------- 1 | ;;; muse-mathml.el --- provide MathML support for Muse 2 | 3 | ;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. 4 | 5 | ;; Author: Li Daobing (lidaobing AT gmail DOT com) 6 | ;; Keywords: Muse mathml hypermedia 7 | 8 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 9 | 10 | ;; Emacs Muse is free software; you can redistribute it and/or modify 11 | ;; it under the terms of the GNU General Public License as published 12 | ;; by the Free Software Foundation; either version 3, or (at your 13 | ;; option) any later version. 14 | 15 | ;; Emacs Muse is distributed in the hope that it will be useful, but 16 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | ;; General Public License for more details. 19 | 20 | ;; You should have received a copy of the GNU General Public License 21 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 22 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23 | ;; Boston, MA 02110-1301, USA. 24 | 25 | ;;;_* Commentary 26 | 27 | ;;;_ + Startup 28 | 29 | ;; 1. Get a copy of itex2MML and install it to `/usr/bin' or 30 | ;; `/usr/local/bin'. 31 | ;; 32 | ;; You can get a copy from 33 | ;; `http://pear.math.pitt.edu/mathzilla/itex2mml.tar.gz'. 34 | 35 | ;; 2. Copy `itex2MML.py' to `/usr/bin' or `/usr/local/bin', if you 36 | ;; do not have this file, create it and do a `chmod a+x itex2MML.py'. 37 | ;; Its content is the following. 38 | 39 | ;; #!/usr/bin/env python 40 | ;; """A wrap for itex2MML 41 | ;; 42 | ;; Delete the extra blank line. 43 | ;; 44 | ;; You can use it as itex2MML. 45 | ;; 46 | ;; For example: 47 | ;; 48 | ;; echo '$a_b$' | itex2MML.py 49 | ;; """ 50 | ;; 51 | ;; import sys 52 | ;; import os 53 | ;; 54 | ;; def main(): 55 | ;; fin, fo = os.popen2('itex2MML') 56 | ;; fin.write(sys.stdin.read()) 57 | ;; fin.close() 58 | ;; for line in fo: 59 | ;; line = line.strip() 60 | ;; if line: 61 | ;; print line 62 | ;; 63 | ;; if __name__ == '__main__': 64 | ;; main() 65 | 66 | ;; 3. Put `muse-math.el' into your `load-path'. 67 | 68 | ;; 4. Add the following to your .emacs file. 69 | ;; 70 | ;; (require 'muse-mathml) 71 | 72 | (require 'muse-html) 73 | (require 'muse-publish) 74 | 75 | (defgroup muse-mathml nil 76 | "Options controlling the behavior of Muse XHTML+MathML publishing. 77 | See `muse-html' for more information." 78 | :group 'muse-publish) 79 | 80 | (defcustom muse-mathml-extension ".xhtml" 81 | "Default file extension for publishing XHTML+MathML files." 82 | :type 'string 83 | :group 'muse-mathml) 84 | 85 | (defcustom muse-mathml-style-sheet muse-xhtml-style-sheet 86 | "Store your stylesheet definitions here. 87 | This is used in `muse-mathml-header'. 88 | You can put raw CSS in here or a tag to an external stylesheet. 89 | This text may contain markup tags. 90 | 91 | An example of using is as follows. 92 | 93 | " 94 | :type 'string 95 | :group 'muse-mathml) 96 | 97 | (defcustom muse-mathml-header 98 | " 99 | (muse-html-encoding)\"?> 100 | 102 | 104 | 105 | <lisp> 106 | (concat (muse-publishing-directive \"title\") 107 | (let ((author (muse-publishing-directive \"author\"))) 108 | (if (not (string= author (user-full-name))) 109 | (concat \" (by \" author \")\"))))</lisp> 110 | 111 | muse-html-meta-http-equiv\" 112 | content=\"muse-html-meta-content-type\" /> 113 | 114 | (let ((maintainer (muse-style-element :maintainer))) 115 | (when maintainer 116 | (concat \"\"))) 117 | 118 | muse-xhtml-style-sheet 119 | 120 | 121 |

122 | (concat (muse-publishing-directive \"title\") 123 | (let ((author (muse-publishing-directive \"author\"))) 124 | (if (not (string= author (user-full-name))) 125 | (concat \" (by \" author \")\"))))

126 | \n" 127 | "Header used for publishing XHTML+MathML files. 128 | This may be text or a filename." 129 | :type 'string 130 | :group 'muse-mathml) 131 | 132 | (defcustom muse-mathml-footer " 133 | 134 | 135 | \n" 136 | "Footer used for publishing XHTML+MathML files. 137 | This may be text or a filename." 138 | :type 'string 139 | :group 'muse-mathml) 140 | 141 | (defcustom muse-mathml-command 142 | (if (or (featurep 'executable) 143 | (load "executable" t t)) 144 | (executable-find "itex2MML.py")) 145 | "Program to use to convert Latex text to MathML." 146 | :type 'string 147 | :group 'muse-mathml) 148 | 149 | (defun muse-publish-mathml-tag (beg end) 150 | (if muse-mathml-command 151 | (muse-publish-command-tag 152 | beg end (list (cons "interp" muse-mathml-command))) 153 | (muse-publish-example-tag beg end))) 154 | 155 | ;; Add the tag 156 | 157 | (add-to-list 'muse-publish-markup-tags 158 | '("mathml" t nil muse-publish-mathml-tag) 159 | t) 160 | 161 | ;; Register the Muse MathML Publisher 162 | 163 | (muse-derive-style "mathml" "xhtml" 164 | :suffix 'muse-mathml-extension 165 | :header 'muse-mathml-header 166 | :footer 'muse-mathml-footer) 167 | 168 | (provide 'muse-mathml) 169 | ;;; muse-mathml.el ends here 170 | -------------------------------------------------------------------------------- /examples/mwolson/stylesheets/common.css: -------------------------------------------------------------------------------- 1 | /* Michael Olson's tweaked Muse stylesheet 2 | 3 | Common elements. 4 | 5 | License: Modification and propagation of this document is 6 | permitted. Attribution of credit to me is optional. 7 | */ 8 | 9 | /* Normal elements */ 10 | 11 | a.nonexistent { 12 | background-color: white; 13 | color: red; 14 | font-weight: bold; 15 | } 16 | 17 | a.nonexistent:visited { 18 | background-color: white; 19 | color: red; 20 | } 21 | 22 | a:link.top, a:visited.top { 23 | color: #F5DEB3; /* wheat */ 24 | line-height: 90%; 25 | position: relative; 26 | text-decoration: none; 27 | top: -13px; 28 | } 29 | 30 | a:link:hover, a:visited:hover { 31 | background-color: #F5F5F5; /* white smoke */ 32 | } 33 | 34 | h1 a:link:hover, h1 a:visited:hover { 35 | background-color: #708090; /* slate gray */ 36 | } 37 | 38 | a:visited { 39 | color: #556B2F; /* dark olive green */ 40 | } 41 | 42 | a:link { 43 | color: #0000CD; /* blue */ 44 | } 45 | 46 | blockquote { 47 | border-left: 2px solid #CCCCCC; /* gray80 */ 48 | padding: 5px; 49 | font-style: italic; 50 | margin: 5px 20px; 51 | } 52 | 53 | body { 54 | background-color: #E5E5E5; /* gainsboro */ 55 | color: black; 56 | margin-left: 2%; 57 | margin-right: 2%; 58 | margin-top: 1%; 59 | } 60 | 61 | code { 62 | margin-left: 3px; 63 | margin-right: 3px; 64 | } 65 | 66 | dt { 67 | font-weight: bold; 68 | margin-top: .5em; 69 | padding: 3px; 70 | } 71 | 72 | em { 73 | font-style: italic; 74 | } 75 | 76 | h1 { 77 | background-color: #2F4F4F; /* dark slate gray */ 78 | color: #F5DEB3; /* wheat */ 79 | border: 1px solid black; 80 | font-size: large; 81 | overflow: hidden; /* don't crowd the menu */ 82 | padding: 0; 83 | white-space: nowrap; 84 | } 85 | 86 | h2 { 87 | border-bottom: solid 2px #708090; /* slate gray */ 88 | clear: left; 89 | font-size: large; 90 | margin-top: 2.5em; 91 | margin-bottom: .5em; 92 | overflow: hidden; /* don't crowd the menu */ 93 | padding-right: 6px; 94 | } 95 | 96 | h3 { 97 | border-bottom: solid 1px #708090; /* slate gray */ 98 | border-right: solid 2px #E5E5E5; /* gainsboro */ 99 | font-size: medium; 100 | margin-top: 2em; 101 | margin-bottom: .5em; 102 | overflow: hidden; /* don't crowd the menu */ 103 | padding-right: 6px; 104 | } 105 | 106 | h4 { 107 | border-bottom: dashed 1px #BEBEBE; /* light gray */ 108 | border-right: solid 2px #E5E5E5; /* gainsboro */ 109 | margin-top: 1.5em; 110 | margin-bottom: .7em; 111 | overflow: hidden; /* don't crowd the menu */ 112 | padding-right: 6px; 113 | } 114 | 115 | hr { 116 | clear: both; 117 | } 118 | 119 | img { 120 | border: 0; 121 | } 122 | 123 | li { 124 | line-height: 1.2em; 125 | margin-top: .7em; 126 | } 127 | 128 | p.verse { 129 | clear: left; 130 | line-height: 2em; 131 | margin-left: 3%; 132 | } 133 | 134 | p { 135 | line-height: 120%; 136 | } 137 | 138 | pre.example { 139 | margin-left: 3%; 140 | margin-top: 1.2em; 141 | margin-bottom: 1.2em; 142 | /* clear: right; */ 143 | } 144 | 145 | pre.src { 146 | margin-left: 0%; 147 | margin-top: 1.2em; 148 | margin-bottom: 1.2em; 149 | /* clear: right; */ 150 | } 151 | 152 | pre.verse { 153 | font-family: inherit; 154 | line-height: 2em; 155 | margin-left: 3%; 156 | } 157 | 158 | pre { 159 | font-family: monospace; 160 | margin-left: 3%; 161 | white-space: pre; 162 | } 163 | 164 | span.footdate { 165 | color: #556B2F; /* dark olive green */ 166 | font-weight: bold; 167 | } 168 | 169 | strong { 170 | font-weight: bold; 171 | } 172 | 173 | table { 174 | overflow: hidden; /* don't crowd the menu */ 175 | } 176 | 177 | table.image { 178 | clear: right; 179 | } 180 | 181 | ul { 182 | list-style-type: disc; 183 | margin-bottom: 1.5em; 184 | } 185 | 186 | /* Menu */ 187 | 188 | .menu { 189 | background-color: #CDCDCD; /* gray/gainsboro */ 190 | border: 1px solid black; 191 | display: inline; 192 | float: right; 193 | clear: both; 194 | margin-left: 10px; 195 | margin-bottom: 5px; 196 | padding: 3px; 197 | } 198 | 199 | .menuitem { 200 | background-color: #E5E5E5; /* gainsboro */ 201 | margin: 0; 202 | padding-top: 2px; 203 | padding-bottom: 3px; 204 | padding-left: 2px; 205 | padding-right: 2px; 206 | text-align: left; 207 | } 208 | 209 | .menuitem a:link, .menuitem a:visited { 210 | color: #0000CD; /* blue */ 211 | display: block; 212 | margin: 0; 213 | padding-top: 2px; 214 | padding-bottom: 3px; 215 | padding-left: 2px; 216 | padding-right: 2px; 217 | } 218 | 219 | .menuitem a:link:hover, .menuitem a:visited:hover { 220 | background-color: #F5F5F5; /* white smoke */ 221 | } 222 | 223 | .menuother { 224 | padding-left: 2px; 225 | padding-right: 2px; 226 | } 227 | 228 | #tooltipbox { 229 | float: right; 230 | visibility: hidden; 231 | } 232 | 233 | #tooltip { 234 | color: #006400; /* dark green */ 235 | } 236 | 237 | /* Footnote */ 238 | 239 | .navfoot hr { 240 | margin-top: 20px; 241 | margin-bottom: 2px; 242 | padding: 0; 243 | height: 4px; 244 | } 245 | 246 | .navfoot a img { 247 | padding-top: 2px; 248 | padding-right: 0; 249 | padding-bottom: 0; 250 | padding-left: 2px; 251 | } 252 | 253 | .navfoot table { 254 | border-spacing: 0; 255 | border-width: 0; 256 | clear: right; 257 | margin: 0; 258 | padding: 0; 259 | } 260 | 261 | .navfoot td { 262 | border-spacing: 0; 263 | border-width: 0; 264 | margin: 0; 265 | padding: 0; 266 | } 267 | 268 | .navfoot td.iconbox { 269 | background-color: #F5F5F5; /* white smoke */ 270 | border-spacing: 0; 271 | border-width: 1; 272 | border-left: 1px solid black; 273 | border-top: 1px solid black; 274 | border-right: 1px solid #D3D3D3; /* light gray */ 275 | border-bottom: 1px solid #D3D3D3; /* light gray */ 276 | margin: 0; 277 | padding-top: 2px; 278 | padding-right: 5px; 279 | padding-bottom: 2px; 280 | padding-left: 2px; 281 | } 282 | -------------------------------------------------------------------------------- /lisp/muse-import-latex.el: -------------------------------------------------------------------------------- 1 | ;;; muse-import-latex.el --- convert a LaTex file into a Muse file 2 | 3 | ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 4 | ;; Free Software Foundation, Inc. 5 | 6 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 7 | 8 | ;; Emacs Muse is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published 10 | ;; by the Free Software Foundation; either version 3, or (at your 11 | ;; option) any later version. 12 | 13 | ;; Emacs Muse is distributed in the hope that it will be useful, but 14 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | ;; General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 20 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 | ;; Boston, MA 02110-1301, USA. 22 | 23 | ;;; Commentary: 24 | 25 | ;; Helper commands for converting a LaTeX file into a Muse file. 26 | 27 | ;;; Contributors: 28 | 29 | ;;; Code: 30 | 31 | (require 'muse) 32 | (require 'muse-regexps) 33 | 34 | (defun muse-i-l-write-citation (note author citation pages) 35 | (save-excursion 36 | (goto-char (point-max)) 37 | (if (= note 1) 38 | (insert "\nFootnotes:\n\n")) 39 | (let ((beg (point))) 40 | (insert "\n[" (number-to-string note) "] " author) 41 | (if (and citation pages) 42 | (insert ", " citation ", " pages)) 43 | (insert "\n") 44 | (goto-char beg) 45 | (while (re-search-forward (concat "p.\\\\[" muse-regexp-blank "\n]+") 46 | nil t) 47 | (replace-match "p.")) 48 | (goto-char beg) 49 | (while (re-search-forward "--" nil t) 50 | (replace-match "-"))))) 51 | 52 | (defun muse-i-l-write-footnote (note text) 53 | (save-excursion 54 | (goto-char (point-max)) 55 | (if (= note 1) 56 | (insert "\nFootnotes:\n\n")) 57 | (insert "\n[" (number-to-string note) "] " text ?\n))) 58 | 59 | ;;;###autoload 60 | (defun muse-import-latex () 61 | (interactive) 62 | (goto-char (point-min)) 63 | (while (not (eobp)) 64 | (cond 65 | ((or (looking-at "^\\\\documentclass") 66 | (looking-at "^\\\\input") 67 | (looking-at "^\\\\begin{document}") 68 | (looking-at "^\\\\end{document}") 69 | (looking-at "^\\\\author") 70 | (looking-at "^\\\\\\(med\\|big\\|small\\)skip") 71 | (looking-at "^\\\\maketitle")) 72 | (delete-region (point) (muse-line-end-position))) 73 | ((looking-at "^\\\\title{\\(.+\\)}") 74 | (delete-region (match-end 1) (muse-line-end-position)) 75 | (delete-region (point) (match-beginning 1)) 76 | (insert "#title "))) 77 | (forward-line)) 78 | (goto-char (point-min)) 79 | (while (re-search-forward "\\\\\\(l\\)?dots{}" nil t) 80 | (replace-match (concat (and (string= (match-string 1) "l") ".") 81 | "..."))) 82 | (goto-char (point-min)) 83 | (while (re-search-forward "\\(``\\|''\\)" nil t) 84 | (replace-match "\"")) 85 | (goto-char (point-min)) 86 | (while (re-search-forward "---" nil t) 87 | (replace-match " -- ")) 88 | (goto-char (point-min)) 89 | (while (re-search-forward "\\\\tableofcontents" nil t) 90 | (replace-match "")) 91 | (goto-char (point-min)) 92 | (while (re-search-forward "\\\\\\\\" nil t) 93 | (replace-match "")) 94 | (goto-char (point-min)) 95 | (while (re-search-forward "\\\\\\(sub\\)?section{\\([^}]+\\)}" nil t) 96 | (replace-match (concat (if (string= (match-string 1) "sub") 97 | "**" "*") 98 | " " (match-string 2)))) 99 | (goto-char (point-min)) 100 | (while (re-search-forward "\\\\\\(begin\\|end\\){verse}" nil t) 101 | (replace-match (concat "<" (if (string= (match-string 1) "end") "/") 102 | "verse>"))) 103 | (goto-char (point-min)) 104 | (while (re-search-forward "\\\\\\(begin\\|end\\){quote}\n" nil t) 105 | (replace-match "")) 106 | (goto-char (point-min)) 107 | (while (re-search-forward 108 | "\\\\\\(emph\\|textbf\\){\\([^}]+?\\)\\(\\\\/\\)?}" nil t) 109 | (replace-match 110 | (if (string= (match-string 1) "emph") "*\\2*" "**\\2**"))) 111 | (let ((footnote-index 1)) 112 | (goto-char (point-min)) 113 | (while (re-search-forward 114 | (concat "\\\\\\(q\\)?\\(footnote\\|excerpt\\)\\(np\\)?" 115 | "\\({\\([^}]+\\)}\\)?" 116 | "\\({\\([^}]+\\)}{\\([^}]+\\)}\\)?{\\([^}]+\\)}") nil t) 117 | (let ((beg (match-beginning 0)) 118 | (end (match-end 0))) 119 | (unless (string= (match-string 2) "footnote") 120 | (if (null (match-string 1)) 121 | (insert " " (match-string 9)) 122 | (let ((b (point)) e) 123 | (insert "\"" (match-string 9) "\"") 124 | (setq e (point-marker)) 125 | (save-match-data 126 | (save-excursion 127 | (goto-char b) 128 | (while (< (point) e) 129 | (if (looking-at "\\s-+") 130 | (delete-region (match-beginning 0) 131 | (match-end 0))) 132 | (forward-line)))) 133 | (set-marker e nil)))) 134 | (insert "[" (number-to-string footnote-index) "]") 135 | (if (string= (match-string 2) "footnote") 136 | (muse-i-l-write-footnote footnote-index (match-string 9)) 137 | (muse-i-l-write-citation footnote-index (match-string 5) 138 | (match-string 7) (match-string 8))) 139 | (setq footnote-index (1+ footnote-index)) 140 | (delete-region beg end)))) 141 | (goto-char (point-min)) 142 | (while (looking-at "\n") (delete-char 1)) 143 | (goto-char (point-min)) 144 | (while (re-search-forward "\n\n+" nil t) 145 | (replace-match "\n\n"))) 146 | 147 | (provide 'muse-import-latex) 148 | 149 | ;;; muse-import-latex.el ends here 150 | -------------------------------------------------------------------------------- /etc/emacs-wiki-migration.txt: -------------------------------------------------------------------------------- 1 | 2 | This document describes the process of migrating from emacs-wiki to Muse. 3 | 4 | Features 5 | ======== 6 | 7 | Muse only 8 | --------- 9 | 10 | Features that exist in Muse, but not emacs-wiki: 11 | 12 | - Nested lists. 13 | 14 | - Publishing to multiple other formats, such as LaTeX and Docbook. 15 | 16 | - Escaping special characters automatically throughout the entire 17 | document, so that you don't have to. 18 | 19 | - Ability to use a different header and footer in different projects, 20 | by creating your own publishing style. 21 | 22 | - Ability to surround some Muse markup with the tag, which 23 | causes is to not be treated as markup. This is useful for 24 | publishing the "|" character as-is, without turning the current 25 | line into a table. 26 | 27 | - Improved detection of paragraphs, which results in HTML that meets 28 | various W3C standards. 29 | 30 | - Journalling mode that is capable of publishing to RSS 2.0 or RSS 31 | 1.0 (RDF). 32 | 33 | - Embedding LaTeX code into a document by turning it into an image. 34 | This is in muse-latex2png.el. 35 | 36 | emacs-wiki only 37 | --------------- 38 | 39 | The reason that most of these have not been implemented is lack of 40 | demand. If you want to see these features implemented, please send an 41 | email to the muse-el-discuss mailing list, describing a good use case 42 | for them. 43 | 44 | - Publishing bookmarks in XBEL format. The bk2site program -- 45 | available separately -- does an adequate job, so this was not 46 | implemented for Muse. 47 | 48 | - Macros, i.e. keywords like %this%, that expand to some text upon 49 | publishing. 50 | 51 | - Global IDs. 52 | 53 | - Menu generation. 54 | 55 | - PGP encryption of regions with the and tags. 56 | 57 | - The tag. 58 | 59 | - Publishing of ChangeLog files. 60 | 61 | - The keybinding `C-c C-r': rename wiki link at point. 62 | 63 | - The keybinding `C-c C-D': delete wiki link at point. 64 | 65 | - The #style directive. 66 | 67 | - Using the title of the page in a generated index page, rather than 68 | the filename of the page. 69 | 70 | Specifying Projects 71 | =================== 72 | 73 | Here is an example emacs-wiki-projects setting. 74 | 75 | (setq emacs-wiki-projects 76 | '(("WebWiki" . 77 | ((emacs-wiki-directories . ("~/WebWiki")) 78 | (emacs-wiki-project-server-prefix . "/web/") 79 | (emacs-wiki-publishing-directory 80 | . "~/public_html/web"))) 81 | ("ProjectsWiki" . 82 | ((emacs-wiki-directories . ("~/ProjectsWiki")) 83 | (emacs-wiki-project-server-prefix . "/projects/") 84 | (emacs-wiki-publishing-directory 85 | . "~/public_html/projects"))))) 86 | 87 | And here is the corresponding muse-project-alist setting. 88 | 89 | (setq muse-project-alist 90 | '(("Website" ("~/WebWiki" 91 | :default "WelcomePage") 92 | (:base "html" 93 | :path "~/public_html/web")) 94 | ("Projects" ("~/ProjectsWiki" 95 | :default "WelcomePage") 96 | (:base "html" 97 | :path "~/public_html/projects")))) 98 | 99 | Note that there is no need to specify a prefix. Muse will 100 | automatically figure out what the relative paths in links to Muse 101 | files should be. 102 | 103 | If you want to be able to link to another project entry that is on a 104 | different domain, then you must use :base-url in every project entry. 105 | An example of this follows. 106 | 107 | (setq muse-project-alist 108 | '(("Website" ("~/WebWiki" 109 | :default "WelcomePage") 110 | (:base "html" 111 | :base-url "http://web.example.org/web" 112 | :path "~/public_html_1/web")) 113 | ("Projects" ("~/ProjectsWiki" 114 | :default "WelcomePage") 115 | (:base "html" 116 | :base-url "http://projects.example.org/projects" 117 | :path "~/public_html_2/projects")))) 118 | 119 | Special Topics 120 | ============== 121 | 122 | Including multiple directories 123 | ------------------------------ 124 | 125 | With emacs-wiki, this was done by setting the 126 | `emacs-wiki-recurse-directories' option to non-nil. 127 | 128 | With Muse, this can be accomplished by including an entry in your 129 | muse-project-alist setting that causes entries for a directory and all 130 | subdirectories to be created. This does not work when using the 131 | customize interface to set `muse-project-alist'. 132 | 133 | Here is an example: 134 | 135 | ("Blog" (,@(muse-project-alist-dirs "~/Blog") 136 | :default "index") 137 | 138 | ;; Publish this directory and its subdirectories. Arguments 139 | ;; are as follows. The above `muse-project-alist-dirs' part 140 | ;; is also needed, using Argument 1. 141 | ;; 142 | ;; 1. Source directory 143 | ;; 2. Output directory 144 | ;; 3. Publishing style 145 | ;; remainder: Other things to put in every generated style 146 | ,@(muse-project-alist-styles "~/Blog" 147 | "~/public_html/blog" 148 | "blosxom")) 149 | 150 | Generating an Index page 151 | ------------------------ 152 | 153 | In emacs-wiki, the page specified by `emacs-wiki-index-page' is an 154 | automatically generated index page. 155 | 156 | Muse does not automatically create this file. If you want an 157 | automatic index file to be generated, then create a file and place the 158 | following contents (between the lines of underscores) in it. 159 | 160 | _____ 161 | #title Index 162 | 163 | (muse-index-as-string t t t) 164 | _____ 165 | 166 | Then, add a :force-publish tag to the paths part of the project entry 167 | in muse-project-alist. Example: 168 | 169 | ("Website" ("~/Web/" 170 | :force-publish ("WikiIndex") 171 | :default "WelcomePage") 172 | (:base "xhtml" 173 | :base-url "http://mydomain.org/" 174 | :path "~/public_html")) 175 | 176 | License 177 | ======= 178 | 179 | This file may be used, distributed, and modified without restriction. 180 | -------------------------------------------------------------------------------- /contrib/ikiwiki/IkiWiki/Plugin/test.pl: -------------------------------------------------------------------------------- 1 | 2 | use warnings; 3 | use strict; 4 | 5 | use IO::Select qw(); 6 | use IO::Socket::INET qw(); 7 | 8 | my %config = ( 9 | muse_emacs => '/usr/local/bin/emacs', 10 | muse_init => '/stuff/proj/personal-site/ikiwiki/muse-init.el', 11 | muse_shared_secret => 'foo', 12 | ); 13 | 14 | my %MUSE_SERVER = ( host => 'localhost' ); 15 | 16 | main(); 17 | exit 0; 18 | 19 | # Determine the emacs binary to use 20 | sub locate_emacs { 21 | my $err = sub { 22 | die "Unable to find your emacs binary.\n", 23 | " Set muse_emacs config to the right value.\n"; 24 | }; 25 | if ( $config{muse_emacs} ) { 26 | ( -x $config{muse_emacs} ) ? return $config{muse_emacs} : $err->(); 27 | } 28 | else { 29 | my $emacs = `which emacs`; 30 | chomp $emacs; 31 | ( $emacs ) ? return $emacs : $err->(); 32 | } 33 | } 34 | 35 | # Initialize connection to the Muse IPC server 36 | sub start_muse_server { 37 | my $secret = $config{muse_shared_secret}; 38 | my $init_port = $config{muse_init_port} || 0; 39 | my $ipc_port = $config{muse_ipc_port}; 40 | 41 | # Perform sanity checks 42 | $config{muse_init} or die "Error: muse_init config option not defined.\n"; 43 | 44 | # Start initialization server 45 | my $pserver = IO::Socket::INET->new( 46 | Proto => 'tcp', 47 | LocalAddr => 'localhost', 48 | LocalPort => $init_port, 49 | Listen => IO::Socket::INET::SOMAXCONN, 50 | ) or die "Error: Cannot begin initialization for the Muse IPC server.\n"; 51 | $pserver->autoflush(1); 52 | $init_port = $pserver->sockport(); 53 | my $select = IO::Select->new($pserver); 54 | 55 | # Start Emacs 56 | defined(my $pid = fork()) or die "Error: Unable to fork.\n"; 57 | if ( $pid ) { 58 | $MUSE_SERVER{pid} = $pid; 59 | } 60 | else { 61 | exec locate_emacs(), 62 | qw( -q --no-site-file -batch -l ), $config{muse_init}, 63 | qw( --eval ), "(muse-ikiwiki-start-server \"$init_port\"" . 64 | ( $ipc_port ? " \"$ipc_port\"" : '' ) . ")"; 65 | die "Error: Unable to exec emacs.\n"; 66 | } 67 | 68 | my $emacs_port = undef; 69 | 70 | SERVER: 71 | # Respond to clients 72 | while ( my @ready = $select->can_read() ) { 73 | for my $client (@ready) { 74 | if ($client == $pserver) { 75 | my $new = $pserver->accept(); 76 | $select->add($new); 77 | next; 78 | } 79 | my $line = <$client>; 80 | chomp $line if defined $line; 81 | if ( defined $line && $line =~ m/^begin (.+)$/s && 82 | $1 eq $secret ) { 83 | print $client "ok\n"; 84 | $line = <$client>; 85 | chomp $line if defined $line; 86 | if ( defined $line && $line =~ m/^port (.+)$/s ) { 87 | $emacs_port = $1; 88 | } 89 | else { 90 | print STDERR <remove($client); 98 | $client->close(); 99 | } 100 | } 101 | $pserver->close(); 102 | 103 | if ( $emacs_port ) { 104 | $MUSE_SERVER{port} = $emacs_port; 105 | } 106 | else { 107 | kill_muse_server(); 108 | } 109 | } 110 | 111 | sub stop_muse_server { 112 | my ( $sock ) = @_; 113 | 114 | if ( $MUSE_SERVER{pid} ) { 115 | # Give Muse 3 seconds to stop, presuming that it has already 116 | # been sent the "done" command via stop_muse_server. 117 | local $SIG{ALRM} = sub { 118 | kill 9, $MUSE_SERVER{pid}; 119 | die "Timeout"; 120 | }; 121 | eval { 122 | alarm 3; 123 | print $sock "done\n"; 124 | $sock->close(); 125 | waitpid($MUSE_SERVER{pid}, 0); 126 | alarm 0; 127 | }; 128 | delete $MUSE_SERVER{pid}; 129 | } 130 | else { 131 | print $sock "done\n"; 132 | $sock->close(); 133 | } 134 | } 135 | 136 | sub kill_muse_server { 137 | my @msgs = @_; 138 | 139 | kill 9, $MUSE_SERVER{pid} if $MUSE_SERVER{pid}; 140 | die @msgs if @msgs; 141 | } 142 | 143 | sub ipc_expect_ok { 144 | my ( $sock, $err_msg ) = @_; 145 | $err_msg = "Error: Command did not succeed on Muse IPC server.\n"; 146 | 147 | my $line = <$sock>; 148 | chomp $line; 149 | if ( $line ne 'ok' ) { 150 | $sock->close(); 151 | kill_muse_server $err_msg; 152 | } 153 | } 154 | 155 | sub ipc_connect { 156 | my $secret = $config{muse_shared_secret}; 157 | my $host = $MUSE_SERVER{host}; 158 | my $port = $MUSE_SERVER{port}; 159 | $host && $port 160 | or kill_muse_server "Error: No Muse IPC server is active.\n"; 161 | 162 | # Start client connection 163 | my $sock = IO::Socket::INET->new( 164 | Proto => 'tcp', 165 | PeerAddr => $host, 166 | PeerPort => $port, 167 | ) or kill_muse_server "Error: Cannot connect to the Muse IPC server.\n"; 168 | $sock->autoflush(1); 169 | 170 | # Authenticate 171 | print $sock "begin $secret\n"; 172 | ipc_expect_ok $sock, 173 | "Error: Could not authenticate to the Muse IPC server.\n"; 174 | 175 | return $sock; 176 | } 177 | 178 | sub test_name { 179 | my ( $sock ) = @_; 180 | 181 | print $sock "name foobar\n"; 182 | ipc_expect_ok $sock, 183 | "Error: Could not set name of page on Muse IPC server.\n"; 184 | } 185 | 186 | sub test_title { 187 | my ( $sock ) = @_; 188 | 189 | print $sock "title quux\n"; 190 | ipc_expect_ok $sock, 191 | "Error: Could not set title of page on Muse IPC server.\n"; 192 | } 193 | 194 | sub main { 195 | print "Starting Muse server ...\n"; 196 | start_muse_server(); 197 | 198 | print "Got port $MUSE_SERVER{port}.\n"; 199 | my $sock = ipc_connect(); 200 | test_name($sock); 201 | test_title($sock); 202 | 203 | print "Shutting down ...\n"; 204 | stop_muse_server($sock); 205 | print "Done shutting down.\n"; 206 | } 207 | -------------------------------------------------------------------------------- /lisp/muse-ipc.el: -------------------------------------------------------------------------------- 1 | ;;; muse-ipc.el --- publish Muse documents from other processes 2 | 3 | ;; Copyright (C) 2009, 2010 Free Software Foundation, Inc. 4 | 5 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 6 | 7 | ;; Emacs Muse is free software; you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published 9 | ;; by the Free Software Foundation; either version 3, or (at your 10 | ;; option) any later version. 11 | 12 | ;; Emacs Muse is distributed in the hope that it will be useful, but 13 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | ;; General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 19 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | ;; Boston, MA 02110-1301, USA. 21 | 22 | ;;; Commentary: 23 | 24 | ;; This file is still in alpha state. Not for production use! 25 | 26 | ;;; Contributors: 27 | 28 | ;;; Code: 29 | 30 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 31 | ;; 32 | ;; Muse Inter-Process Communication 33 | ;; 34 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 35 | 36 | (eval-when-compile (require 'cl)) 37 | 38 | (require 'muse) 39 | (require 'muse-publish) 40 | 41 | (defgroup muse-ipc nil 42 | "Options controlling the behavior of Muse's IPC module." 43 | :group 'muse-publish) 44 | 45 | (defcustom muse-ipc-timeout 60 46 | "Maximum time to wait for a client to respond." 47 | :group 'muse-ipc 48 | :type 'number) 49 | 50 | (defcustom muse-ipc-ignore-done nil 51 | "If non-nil, ignore any 'done' messages that we get from clients." 52 | :group 'muse-ipc 53 | :type 'boolean) 54 | 55 | (defvar muse-ipc-server-port nil 56 | "Port of the Emacs server.") 57 | 58 | (defvar muse-ipc-server-process nil 59 | "Process of the Emacs server.") 60 | 61 | (defvar muse-ipc-server-registered nil 62 | "Whether we have successfully registered our port with the client.") 63 | 64 | (defun muse-ipc-init-filter (proc string) 65 | "Handle data from client while initiating a connection." 66 | (unless muse-ipc-server-registered 67 | (when (string-match "\\`ok$" string) 68 | (setq muse-ipc-server-registered t)))) 69 | 70 | (defun muse-ipc-delete-client (proc) 71 | "Delete a client." 72 | (let ((buffer (process-get proc :buffer))) 73 | (when (and buffer (buffer-live-p buffer)) 74 | (with-current-buffer buffer 75 | (set-buffer-modified-p nil)) 76 | (kill-buffer buffer))) 77 | (when (eq (process-status proc) 'open) 78 | (delete-process proc))) 79 | 80 | (defun* muse-ipc-server-filter (proc string) 81 | "Handle data from a client after it connects." 82 | ;; Authenticate 83 | (unless (process-get proc :authenticated) 84 | (if (and (string-match "\\`begin \\(.+\\)$" string) 85 | (equal (match-string 1 string) 86 | (process-get proc :shared-secret))) 87 | (progn 88 | (setq string (substring string (match-end 0))) 89 | (process-put proc :authenticated t) 90 | (process-send-string proc "ok\n")) 91 | (process-send-string proc "nok\n") 92 | (delete-process proc)) 93 | (return-from muse-ipc-server-filter)) 94 | 95 | ;; Handle case where the client is sending data to be published 96 | (when (process-get proc :sending-data) 97 | (with-current-buffer (process-get proc :buffer) 98 | (insert string) 99 | (let ((buf-len (1- (point))) 100 | (expected-len (process-get proc :data-bytes))) 101 | (cond ((= buf-len expected-len) 102 | (process-put proc :sending-data nil)) 103 | ((> buf-len expected-len) 104 | (process-send-string proc "nok\n") 105 | (muse-ipc-delete-client proc))))) 106 | (return-from muse-ipc-server-filter)) 107 | 108 | ;; Dispatch commands 109 | (cond 110 | ((string-match "\\`done$" string) 111 | ;; done, close the server 112 | (unless muse-ipc-ignore-done 113 | (muse-ipc-stop-server))) 114 | 115 | ((string-match "\\`name \\(.+\\)$" string) 116 | ;; set name 117 | (process-put proc :file-name (match-string 1 string)) 118 | (process-send-string proc "ok\n")) 119 | 120 | ((string-match "\\`title \\(.+\\)$" string) 121 | ;; set title 122 | (process-put proc :title (match-string 1 string)) 123 | (process-send-string proc "ok\n")) 124 | 125 | (t 126 | ;; unrecognized command 127 | (process-send-string proc "nok\n")))) 128 | 129 | (defun muse-ipc-stop-server () 130 | "Stop Muse IPC server and reset connection data." 131 | (stop-process muse-ipc-server-process) 132 | (delete-process muse-ipc-server-process) 133 | (setq muse-ipc-server-port nil) 134 | (setq muse-ipc-server-process nil)) 135 | 136 | (defun muse-ipc-start (shared-secret publish-fn client-port &optional server-port) 137 | "Start an IPC connection and send a response to CLIENT-PORT. 138 | If SERVER-PORT is provided, start the IPC server on that port, otherwise 139 | choose a random port. 140 | 141 | SHARED-SECRET is used as a very minimal security measure to 142 | authenticate the Muse IPC server during initialization, and also 143 | any incoming clients once the server is started. 144 | 145 | PUBLISH-FN is the function which should be called in buffer of 146 | the received contents. It should transform the buffer into a 147 | published state. It must take at least two arguments. The first 148 | argument is the full path of the file that the contents 149 | correspond with. The second argument is the title to use when 150 | publishing the file." 151 | (when (stringp client-port) 152 | (setq client-port (string-to-number client-port))) 153 | (when (stringp server-port) 154 | (setq server-port (string-to-number server-port))) 155 | (setq muse-ipc-server-process 156 | (make-network-process 157 | :name "muse-ipc" 158 | :buffer nil 159 | :host 'local :service (or server-port t) 160 | :server t :noquery t :nowait t 161 | :plist (list :authenticated nil :shared-secret shared-secret 162 | :publish-fn publish-fn) 163 | :filter 'muse-ipc-server-filter)) 164 | (unless muse-ipc-server-process 165 | (error "Error: Could not start Muse IPC Server process")) 166 | (set-process-coding-system muse-ipc-server-process 167 | 'raw-text-unix 'raw-text-unix) 168 | (setq muse-ipc-server-port 169 | (number-to-string 170 | (cadr (process-contact muse-ipc-server-process)))) 171 | (let ((client-proc 172 | (make-network-process 173 | :name "muse-ipc-client" 174 | :buffer nil 175 | :host 'local :service client-port 176 | :noquery t 177 | :filter 'muse-ipc-init-filter))) 178 | (setq muse-ipc-server-registered nil) 179 | (process-send-string client-proc 180 | (concat "begin " shared-secret "\n")) 181 | (accept-process-output client-proc muse-ipc-timeout nil t) 182 | (unless muse-ipc-server-registered 183 | (error "Error: Did not register listener")) 184 | (process-send-string client-proc 185 | (concat "port " muse-ipc-server-port "\n")) 186 | (stop-process client-proc) 187 | (delete-process client-proc)) 188 | 189 | ;; Accept process output until the server dies 190 | (while muse-ipc-server-process (accept-process-output nil 1))) 191 | 192 | (provide 'muse-ipc) 193 | 194 | ;;; muse-ipc.el ends here 195 | -------------------------------------------------------------------------------- /contrib/cgi.el: -------------------------------------------------------------------------------- 1 | ;;; cgi.el -- using Emacs for CGI scripting 2 | ;;; 3 | ;;; Author: Eric Marsden 4 | ;;; Michael Olson (slight modifications) 5 | ;;; Keywords: CGI web scripting slow 6 | ;;; Version: 0.3 7 | ;;; Time-stamp: <2001-08-24 emarsden> 8 | ;;; Copyright: (C) 2000 Eric Marsden 9 | ;;; Parts copyright (C) 2006 Free Software Foundation, Inc. 10 | ;; 11 | ;; This program is free software; you can redistribute it and/or 12 | ;; modify it under the terms of the GNU General Public License as 13 | ;; published by the Free Software Foundation; either version 3 of 14 | ;; the License, or (at your option) any later version. 15 | ;; 16 | ;; This program is distributed in the hope that it will be useful, 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | ;; GNU General Public License for more details. 20 | ;; 21 | ;; You should have received a copy of the GNU General Public 22 | ;; License along with this program; if not, write to the Free 23 | ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 24 | ;; MA 02111-1307, USA. 25 | ;; 26 | ;; 27 | ;;; Commentary: 28 | ;; 29 | ;; People who like this sort of thing will find this the sort of 30 | ;; thing they like. -- Abraham Lincoln 31 | ;; 32 | ;; 33 | ;; Overview ========================================================== 34 | ;; 35 | ;; A simple library for the Common Gateway Interface for Emacs, 36 | ;; allowing you to service requests for non static web pages in elisp. 37 | ;; Provides routines for decoding arguments to GET- and POST-type CGI 38 | ;; requests. 39 | ;; 40 | ;; Usage: place a shell script such as the following in your web 41 | ;; server's CGI directory (typically called something like 42 | ;; /var/www/cgi-bin/): 43 | ;; 44 | ;; ,------------------------------------------------------------------- 45 | ;; | #!/bin/sh 46 | ;; | 47 | ;; | emacs -batch -l cgi.el -f cgi-calendar 48 | ;; `------------------------------------------------------------------- 49 | ;; 50 | ;; (`cgi-calendar' is a sample elisp CGI script provided at the end of 51 | ;; this file). 52 | ;; 53 | ;; Alternatively, if you're running version 2.x of the linux kernel 54 | ;; you could make .elc files directly executable via the binfmt_misc 55 | ;; mechanism and run them straight from the cgi-bin directory. 56 | ;; 57 | ;; Efficiency would be improved by having Emacs bind to the http 58 | ;; service port and spawn a thread per connection. Extending Emacs to 59 | ;; support server sockets and multithreading is left as an exercise 60 | ;; for the reader. 61 | ;; 62 | ;; References: 63 | ;; * rfc1738 "Uniform Resource Locators" 64 | ;; * rfc1630 "Universal Resource Identifiers in WWW" 65 | ;; 66 | ;; Thanks to Christoph Conrad for pointing 67 | ;; out a bug in the URI-decoding. 68 | 69 | ;;; Code: 70 | 71 | (eval-when-compile 72 | (require 'cl) 73 | (require 'calendar)) 74 | 75 | (defconst cgi-url-unreserved-chars '( 76 | ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m 77 | ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z 78 | ?A ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M 79 | ?N ?O ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z 80 | ?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 81 | ?\$ ?\- ?\_ ?\. ?\! ?\~ ?\* ?\' ?\( ?\) ?\,)) 82 | 83 | (defun cgi-int-char (i) 84 | (if (fboundp 'int-char) (int-char i) i)) 85 | 86 | (defun cgi-hex-char-p (ch) 87 | (declare (character ch)) 88 | (let ((hexchars '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 89 | ?A ?B ?C ?D ?E ?F))) 90 | (member (upcase ch) hexchars))) 91 | 92 | ;; decode %xx to the corresponding character and + to ' ' 93 | (defun cgi-decode-string (str) 94 | (do ((i 0) 95 | (len (length str)) 96 | (decoded '())) 97 | ((>= i len) (concat (nreverse decoded))) 98 | (let ((ch (aref str i))) 99 | (cond ((eq ?+ ch) 100 | (push ?\ decoded) 101 | (incf i)) 102 | ((and (eq ?% ch) 103 | (< (+ i 2) len) 104 | (cgi-hex-char-p (aref str (+ i 1))) 105 | (cgi-hex-char-p (aref str (+ i 2)))) 106 | (let ((hex (string-to-number (substring str (+ i 1) (+ i 3)) 16))) 107 | (push (cgi-int-char hex) decoded) 108 | (incf i 3))) 109 | (t (push ch decoded) 110 | (incf i)))))) 111 | 112 | (defun cgi-position (item seq &optional start end) 113 | (or start (setq start 0)) 114 | (or end (setq end (length seq))) 115 | (while (and (< start end) 116 | (not (equal item (aref seq start)))) 117 | (setq start (1+ start))) 118 | (and (< start end) start)) 119 | 120 | ;; Parse "foo=x&bar=y+re" into (("foo" . "x") ("bar" . "y re")) 121 | ;; Substrings are plus-decoded and then URI-decoded. 122 | (defun cgi-decode (q) 123 | (when q 124 | (flet ((split-= (str) 125 | (let ((pos (or (cgi-position ?= str) 0))) 126 | (cons (cgi-decode-string (substring str 0 pos)) 127 | (cgi-decode-string (substring str (+ pos 1))))))) 128 | (mapcar #'split-= (split-string q "&"))))) 129 | 130 | (defun cgi-lose (fmt &rest args) 131 | (let ((why (apply #'format fmt args))) 132 | (message "Script error: %s" why) ; to error_log 133 | (princ "Content-type: text/html\n\n") ; to browser 134 | (princ "Script error\r\n") 135 | (princ "

Script error

\r\n

\r\n") 136 | (princ why) 137 | (princ "\r\n\r\n") 138 | (kill-emacs 0))) 139 | 140 | (defmacro cgi-evaluate (&rest forms) 141 | `(condition-case why 142 | (princ (with-output-to-string ,@forms)) 143 | (error (cgi-lose "Emacs Lisp error: %s" why)))) 144 | 145 | (defun cgi-arguments () 146 | (let ((method (getenv "REQUEST_METHOD")) 147 | req buf) 148 | (cond ((null method) 149 | (cgi-lose "No request method specified")) 150 | ((string= "GET" method) 151 | (unless (getenv "QUERY_STRING") 152 | (cgi-lose "No query string for GET request")) 153 | (cgi-decode (getenv "QUERY_STRING"))) 154 | ((string= "POST" method) 155 | (setq req (getenv "CONTENT_LENGTH")) 156 | (unless req 157 | (cgi-lose "No content-length for POST request")) 158 | (setq buf (get-buffer-create " *cgi*")) 159 | (set-buffer buf) 160 | (erase-buffer) 161 | (loop for i from 1 to (string-to-number req) 162 | do (insert (read-event))) 163 | (cgi-decode (buffer-string))) 164 | (t 165 | (cgi-lose "Can't handle request method %s" method))))) 166 | 167 | ;; ==================================================================== 168 | ;; a sample application: calendar via the web. If invoked without 169 | ;; arguments, presents a calendar for the three months around the 170 | ;; current date. You can request a calendar for a specific period by 171 | ;; specifying the year and the month in the query string: 172 | ;; 173 | ;; ~$ lynx -dump 'http://localhost/cgi-bin/cal?year=1975&month=6' 174 | ;; 175 | ;; When run in batch mode, text normally displayed in the echo area 176 | ;; (via `princ' for example) goes to stdout, and thus to the browser. 177 | ;; Text output using `message' goes to stderr, and thus normally to 178 | ;; your web server's error_log. 179 | ;; ==================================================================== 180 | 181 | (eval-and-compile 182 | (if (fboundp 'calendar-extract-month) 183 | (defalias 'cgi-calendar-extract-month 'calendar-extract-month) 184 | (defalias 'cgi-calendar-extract-month 'extract-calendar-month)) 185 | 186 | (if (fboundp 'calendar-extract-year) 187 | (defalias 'cgi-calendar-extract-year 'calendar-extract-year) 188 | (defalias 'cgi-calendar-extract-year 'extract-calendar-year)) 189 | 190 | (if (fboundp 'calendar-generate) 191 | (defalias 'cgi-calendar-generate 'calendar-generate) 192 | (defalias 'cgi-calendar-generate 'generate-calendar))) 193 | 194 | (defun cgi-calendar-string () 195 | (require 'calendar) 196 | (let* ((args (cgi-arguments)) 197 | (now (calendar-current-date)) 198 | (mnth (cdr (assoc "month" args))) 199 | (month (if mnth (string-to-number mnth) 200 | (cgi-calendar-extract-month now))) 201 | (yr (cdr (assoc "year" args))) 202 | (year (if yr (string-to-number yr) 203 | (cgi-calendar-extract-year now)))) 204 | (with-temp-buffer 205 | (cgi-calendar-generate month year) 206 | (buffer-string)))) 207 | 208 | (defun cgi-calendar () 209 | (cgi-evaluate 210 | (princ "Content-type: text/html\n\n") 211 | (princ "Emacs calendar\r\n") 212 | (princ "

Emacs calendar

\r\n") 213 | (princ "
\r\n")
214 |    (princ (cgi-calendar-string))
215 |    (princ "\r\n
\r\n"))) 216 | 217 | (provide 'cgi) 218 | 219 | ;; cgi.el ends here 220 | -------------------------------------------------------------------------------- /lisp/muse-xml-common.el: -------------------------------------------------------------------------------- 1 | ;;; muse-xml-common.el --- common routines for XML-like publishing styles 2 | 3 | ;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 4 | ;; Free Software Foundation, Inc. 5 | 6 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 7 | 8 | ;; Emacs Muse is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published 10 | ;; by the Free Software Foundation; either version 3, or (at your 11 | ;; option) any later version. 12 | 13 | ;; Emacs Muse is distributed in the hope that it will be useful, but 14 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | ;; General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 20 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 | ;; Boston, MA 02110-1301, USA. 22 | 23 | ;;; Commentary: 24 | 25 | ;;; Contributors: 26 | 27 | ;;; Code: 28 | 29 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 30 | ;; 31 | ;; Muse XML Publishing - Common Elements 32 | ;; 33 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 34 | 35 | (require 'muse-publish) 36 | (require 'muse-regexps) 37 | 38 | (defcustom muse-xml-encoding-map 39 | '((iso-8859-1 . "iso-8859-1") 40 | (iso-2022-jp . "iso-2022-jp") 41 | (utf-8 . "utf-8") 42 | (japanese-iso-8bit . "euc-jp") 43 | (chinese-big5 . "big5") 44 | (mule-utf-8 . "utf-8") 45 | (chinese-iso-8bit . "gb2312") 46 | (chinese-gbk . "gbk")) 47 | "An alist mapping Emacs coding systems to appropriate XML charsets. 48 | Use the base name of the coding system (i.e. without the -unix)." 49 | :type '(alist :key-type coding-system :value-type string) 50 | :group 'muse-xml) 51 | 52 | (defun muse-xml-transform-content-type (content-type default) 53 | "Using `muse-xml-encoding-map', try and resolve an Emacs coding 54 | system to an associated XML coding system. 55 | If no match is found, the DEFAULT charset is used instead." 56 | (let ((match (and (fboundp 'coding-system-base) 57 | (assoc (coding-system-base content-type) 58 | muse-xml-encoding-map)))) 59 | (if match 60 | (cdr match) 61 | default))) 62 | 63 | (defcustom muse-xml-markup-specials 64 | '((?\" . """) 65 | (?\< . "<") 66 | (?\> . ">") 67 | (?\& . "&")) 68 | "A table of characters which must be represented specially." 69 | :type '(alist :key-type character :value-type string) 70 | :group 'muse-xml) 71 | 72 | (defcustom muse-xml-markup-specials-url-extra 73 | '((?\" . """) 74 | (?\< . "<") 75 | (?\> . ">") 76 | (?\& . "&") 77 | (?\ . "%20") 78 | (?\n . "%0D%0A")) 79 | "A table of characters which must be represented specially. 80 | These are extra characters that are escaped within URLs." 81 | :type '(alist :key-type character :value-type string) 82 | :group 'muse-xml) 83 | 84 | (defun muse-xml-decide-specials (context) 85 | "Determine the specials to escape, depending on CONTEXT." 86 | (cond ((memq context '(email url image)) 87 | 'muse-xml-escape-url) 88 | ((eq context 'url-extra) 89 | muse-xml-markup-specials-url-extra) 90 | (t muse-xml-markup-specials))) 91 | 92 | (defun muse-xml-escape-url (str) 93 | "Convert to character entities any non-alphanumeric characters 94 | outside a few punctuation symbols, that risk being misinterpreted 95 | if not escaped." 96 | (when str 97 | (setq str (muse-publish-escape-specials-in-string str 'url-extra)) 98 | (let (pos code len ch) 99 | (save-match-data 100 | (while (setq pos (string-match (concat "[^-" 101 | muse-regexp-alnum 102 | "/:._=@\\?~#%\"\\+<>()&;]") 103 | str pos)) 104 | (setq ch (aref str pos) 105 | code (concat "&#" (int-to-string 106 | (cond ((fboundp 'char-to-ucs) 107 | (char-to-ucs ch)) 108 | ((fboundp 'char-to-int) 109 | (char-to-int ch)) 110 | (t ch))) 111 | ";") 112 | len (length code) 113 | str (concat (substring str 0 pos) 114 | code 115 | (when (< pos (length str)) 116 | (substring str (1+ pos) nil))) 117 | pos (+ len pos))) 118 | str)))) 119 | 120 | (defun muse-xml-markup-anchor () 121 | (unless (get-text-property (match-end 1) 'muse-link) 122 | (let ((text (muse-markup-text 'anchor (match-string 2)))) 123 | (save-match-data 124 | (skip-chars-forward (concat muse-regexp-blank "\n")) 125 | (when (looking-at (concat "<\\([^" muse-regexp-blank "/>\n]+\\)>")) 126 | (goto-char (match-end 0))) 127 | (muse-insert-markup text))) 128 | (match-string 1))) 129 | 130 | (defun muse-xml-sort-table (table) 131 | "Sort the given table structure so that it validates properly." 132 | ;; Note that the decision matrix must have a nil diagonal, or else 133 | ;; elements with the same type will be reversed with respect to each 134 | ;; other. 135 | (let ((decisions '((nil nil nil) ; body < header, body < footer 136 | (t nil t) ; header stays where it is 137 | (t nil nil)))) ; footer < header 138 | (sort table #'(lambda (l r) 139 | (and (integerp (car l)) (integerp (car r)) 140 | (nth (1- (car r)) 141 | (nth (1- (car l)) decisions))))))) 142 | 143 | (defun muse-xml-markup-table (&optional attributes) 144 | "Publish the matched region into a table. 145 | If a string ATTRIBUTES is given, pass it to the markup string begin-table." 146 | (let* ((table-info (muse-publish-table-fields (match-beginning 0) 147 | (match-end 0))) 148 | (row-len (car table-info)) 149 | (supports-group (not (string= (muse-markup-text 'begin-table-group 150 | row-len) 151 | ""))) 152 | (field-list (muse-xml-sort-table (cdr table-info))) 153 | last-part) 154 | (when table-info 155 | (let ((beg (point))) 156 | (muse-publish-ensure-block beg)) 157 | (muse-insert-markup (muse-markup-text 'begin-table (or attributes ""))) 158 | (muse-insert-markup (muse-markup-text 'begin-table-group row-len)) 159 | (dolist (fields field-list) 160 | (let* ((type (car fields)) 161 | (part (cond ((eq type 'hline) nil) 162 | ((= type 1) "tbody") 163 | ((= type 2) "thead") 164 | ((= type 3) "tfoot"))) 165 | (col (cond ((eq type 'hline) nil) 166 | ((= type 1) "td") 167 | ((= type 2) "th") 168 | ((= type 3) "td")))) 169 | (setq fields (cdr fields)) 170 | (unless (and part last-part (string= part last-part)) 171 | (when last-part 172 | (muse-insert-markup " \n") 173 | (when (eq type 'hline) 174 | ;; horizontal separators are represented by closing 175 | ;; the current table group and opening a new one 176 | (muse-insert-markup (muse-markup-text 'end-table-group)) 177 | (muse-insert-markup (muse-markup-text 'begin-table-group 178 | row-len)))) 179 | (when part 180 | (muse-insert-markup " <" part ">\n")) 181 | (setq last-part part)) 182 | (unless (eq type 'hline) 183 | (muse-insert-markup (muse-markup-text 'begin-table-row)) 184 | (dolist (field fields) 185 | (muse-insert-markup (muse-markup-text 'begin-table-entry col)) 186 | (insert field) 187 | (muse-insert-markup (muse-markup-text 'end-table-entry col))) 188 | (muse-insert-markup (muse-markup-text 'end-table-row))))) 189 | (when last-part 190 | (muse-insert-markup " \n")) 191 | (muse-insert-markup (muse-markup-text 'end-table-group)) 192 | (muse-insert-markup (muse-markup-text 'end-table)) 193 | (insert ?\n)))) 194 | 195 | (defun muse-xml-prepare-buffer () 196 | (set (make-local-variable 'muse-publish-url-transforms) 197 | (cons 'muse-xml-escape-string muse-publish-url-transforms))) 198 | 199 | (provide 'muse-xml-common) 200 | 201 | ;;; muse-xml-common.el ends here 202 | -------------------------------------------------------------------------------- /lisp/muse-poem.el: -------------------------------------------------------------------------------- 1 | ;;; muse-poem.el --- publish a poem to LaTex or PDF 2 | 3 | ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 4 | ;; Free Software Foundation, Inc. 5 | 6 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 7 | 8 | ;; Emacs Muse is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published 10 | ;; by the Free Software Foundation; either version 3, or (at your 11 | ;; option) any later version. 12 | 13 | ;; Emacs Muse is distributed in the hope that it will be useful, but 14 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | ;; General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 20 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 | ;; Boston, MA 02110-1301, USA. 22 | 23 | ;;; Commentary: 24 | 25 | ;; This file specifies a form for recording poetry. It is as follows. 26 | ;; 27 | ;; Title 28 | ;; 29 | ;; 30 | ;; Body of poem 31 | ;; 32 | ;; 33 | ;; Annotations, history, notes, etc. 34 | ;; 35 | ;; The `muse-poem' module makes it easy to attractively publish and 36 | ;; reference poems in this format, using the "memoir" module for LaTeX 37 | ;; publishing. It will also markup poems for every other output 38 | ;; style, though none are nearly as pretty. 39 | ;; 40 | ;; Once a poem is written in this format, just publish it to PDF using 41 | ;; the "poem-pdf" style. To make an inlined reference to a poem that 42 | ;; you've written -- for example, from a blog page -- there is a 43 | ;; "poem" tag defined by this module: 44 | ;; 45 | ;; 46 | ;; 47 | ;; Let's assume the template above was called "name.of.poem.page"; 48 | ;; then the above tag would result in this inclusion: 49 | ;; 50 | ;; ** Title 51 | ;; 52 | ;; > Body of poem 53 | ;; 54 | ;; I use this module for publishing all of the poems on my website, 55 | ;; which are at: http://www.newartisans.com/johnw/poems.html. 56 | 57 | ;;; Contributors: 58 | 59 | ;;; Code: 60 | 61 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 62 | ;; 63 | ;; Muse Poem Publishing 64 | ;; 65 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 66 | 67 | (require 'muse-latex) 68 | (require 'muse-project) 69 | 70 | (defgroup muse-poem nil 71 | "Rules for marking up a Muse file as a LaTeX article." 72 | :group 'muse-latex) 73 | 74 | (defcustom muse-poem-latex-header 75 | "\\documentclass[14pt,oneside]{memoir} 76 | 77 | \\usepackage[english]{babel} 78 | \\usepackage[latin1]{inputenc} 79 | \\usepackage[T1]{fontenc} 80 | 81 | \\setlength{\\beforepoemtitleskip}{-5.0ex} 82 | 83 | \\begin{document} 84 | 85 | \\pagestyle{empty} 86 | 87 | \\renewcommand{\\poemtoc}{section} 88 | \\settocdepth{section} 89 | 90 | \\mbox{} 91 | \\vfill 92 | 93 | \\poemtitle{(muse-publishing-directive \"title\")} 94 | 95 | \\settowidth{\\versewidth}{muse-poem-longest-line}\n\n" 96 | "Header used for publishing LaTeX poems. This may be text or a filename." 97 | :type 'string 98 | :group 'muse-poem) 99 | 100 | (defcustom muse-poem-latex-footer "\n\\vfill 101 | \\mbox{} 102 | 103 | \\end{document}" 104 | "Footer used for publishing LaTeX files. This may be text or a filename." 105 | :type 'string 106 | :group 'muse-poem) 107 | 108 | (defcustom muse-poem-markup-strings 109 | '((begin-verse . "\\begin{verse}[\\versewidth]\n") 110 | (verse-space . "\\vin ")) 111 | "Strings used for marking up poems. 112 | These cover the most basic kinds of markup, the handling of which 113 | differs little between the various styles." 114 | :type '(alist :key-type symbol :value-type string) 115 | :group 'muse-poem) 116 | 117 | (defcustom muse-chapbook-latex-header 118 | "\\documentclass{book} 119 | 120 | \\usepackage[english]{babel} 121 | \\usepackage[latin1]{inputenc} 122 | \\usepackage[T1]{fontenc} 123 | 124 | \\setlength{\\beforepoemtitleskip}{-5.0ex} 125 | 126 | \\begin{document} 127 | 128 | \\title{(muse-publishing-directive \"title\")} 129 | \\author{(muse-publishing-directive \"author\")} 130 | \\date{(muse-publishing-directive \"date\")} 131 | 132 | \\maketitle 133 | 134 | \\tableofcontents 135 | 136 | \\renewcommand{\\poemtoc}{section} 137 | \\settocdepth{section}\n" 138 | "Header used for publishing a book of poems in LaTeX form. 139 | This may be text or a filename." 140 | :type 'string 141 | :group 'muse-poem) 142 | 143 | (defcustom muse-chapbook-latex-footer "\n\\end{document}" 144 | "Footer used for publishing a book of poems in LaTeX form. 145 | This may be text or a filename." 146 | :type 'string 147 | :group 'muse-poem) 148 | 149 | (defvar muse-poem-longest-line "") 150 | 151 | (defcustom muse-poem-chapbook-strings 152 | '((begin-verse . "\\newpage 153 | \\mbox{} 154 | \\vfill 155 | 156 | \\poemtitle{(muse-publishing-directive \"title\")} 157 | 158 | \\settowidth{\\versewidth}{muse-poem-longest-line} 159 | 160 | \\begin{verse}[\\versewidth]\n") 161 | (end-verse . "\n\\end{verse}\n\\vfill\n\\mbox{}") 162 | (verse-space . "\\vin ")) 163 | "Strings used for marking up books of poems. 164 | These cover the most basic kinds of markup, the handling of which 165 | differs little between the various styles." 166 | :type '(alist :key-type symbol :value-type string) 167 | :group 'muse-poem) 168 | 169 | (defun muse-poem-prepare-buffer () 170 | (goto-char (point-min)) 171 | (insert "#title ") 172 | (forward-line 1) 173 | (delete-region (point) (1+ (muse-line-end-position))) 174 | (insert "\n") 175 | (let ((beg (point)) end line) 176 | (if (search-forward "\n\n\n" nil t) 177 | (progn 178 | (setq end (copy-marker (match-beginning 0) t)) 179 | (replace-match "\n\n") 180 | (delete-region (point) (point-max))) 181 | (goto-char (point-max)) 182 | (setq end (point)) 183 | (insert "\n")) 184 | (goto-char (1+ beg)) 185 | (set (make-local-variable 'muse-poem-longest-line) "") 186 | (while (< (point) end) 187 | (setq line (buffer-substring-no-properties (point) 188 | (muse-line-end-position))) 189 | (if (> (length line) (length muse-poem-longest-line)) 190 | (setq muse-poem-longest-line line)) 191 | (forward-line 1)) 192 | nil)) 193 | 194 | (defvar muse-poem-tag '("poem" nil t nil muse-poem-markup-tag)) 195 | 196 | (defun muse-poem-markup-tag (beg end attrs) 197 | "This markup tag allows a poem to be included from another project page. 198 | The form of usage is: 199 | " 200 | (let ((page (cdr (assoc (cdr (assoc "title" attrs)) 201 | (muse-project-file-alist)))) 202 | beg end) 203 | (if (null page) 204 | (insert " *Reference to\n unknown poem \"" 205 | (cdr (assoc "title" attrs)) "\".*\n") 206 | (setq beg (point)) 207 | (insert 208 | (muse-with-temp-buffer 209 | (muse-insert-file-contents page) 210 | (goto-char (point-min)) 211 | (if (assoc "nohead" attrs) 212 | (progn 213 | (forward-line 3) 214 | (delete-region (point-min) (point))) 215 | (insert "** ") 216 | (search-forward "\n\n\n") 217 | (replace-match "\n\n")) 218 | (if (search-forward "\n\n\n" nil t) 219 | (setq end (match-beginning 0)) 220 | (setq end (point-max))) 221 | (buffer-substring-no-properties (point-min) end))) 222 | (setq end (point-marker)) 223 | (goto-char beg) 224 | (unless (assoc "nohead" attrs) 225 | (forward-line 2)) 226 | (while (< (point) end) 227 | (insert "> ") 228 | (forward-line 1)) 229 | (set-marker end nil)))) 230 | 231 | (put 'muse-poem-markup-tag 'muse-dangerous-tag t) 232 | 233 | (add-to-list 'muse-publish-markup-tags muse-poem-tag) 234 | 235 | ;;; Register the Muse POEM Publishers 236 | 237 | (muse-derive-style "poem-latex" "latex" 238 | :before 'muse-poem-prepare-buffer 239 | :strings 'muse-poem-markup-strings 240 | :header 'muse-poem-latex-header 241 | :footer 'muse-poem-latex-footer) 242 | 243 | (muse-derive-style "poem-pdf" "pdf" 244 | :before 'muse-poem-prepare-buffer 245 | :strings 'muse-poem-markup-strings 246 | :header 'muse-poem-latex-header 247 | :footer 'muse-poem-latex-footer) 248 | 249 | (muse-derive-style "chapbook-latex" "latex" 250 | :before 'muse-poem-prepare-buffer 251 | :strings 'muse-poem-chapbook-strings 252 | :header 'muse-chapbook-latex-header 253 | :footer 'muse-chapbook-latex-footer) 254 | 255 | (muse-derive-style "chapbook-pdf" "pdf" 256 | :before 'muse-poem-prepare-buffer 257 | :strings 'muse-poem-chapbook-strings 258 | :header 'muse-chapbook-latex-header 259 | :footer 'muse-chapbook-latex-footer) 260 | 261 | (provide 'muse-poem) 262 | 263 | ;;; muse-poem.el ends here 264 | -------------------------------------------------------------------------------- /lisp/muse-ikiwiki.el: -------------------------------------------------------------------------------- 1 | ;;; muse-ikiwiki.el --- integrate with Ikiwiki 2 | 3 | ;; Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. 4 | 5 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 6 | 7 | ;; Emacs Muse is free software; you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published 9 | ;; by the Free Software Foundation; either version 3, or (at your 10 | ;; option) any later version. 11 | 12 | ;; Emacs Muse is distributed in the hope that it will be useful, but 13 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | ;; General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 19 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | ;; Boston, MA 02110-1301, USA. 21 | 22 | ;;; Commentary: 23 | 24 | ;;; Contributors: 25 | 26 | ;;; Code: 27 | 28 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 29 | ;; 30 | ;; Muse Ikiwiki Integration 31 | ;; 32 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 33 | 34 | (require 'muse) 35 | (require 'muse-html) 36 | (require 'muse-ipc) 37 | (require 'muse-publish) 38 | 39 | (eval-when-compile 40 | (require 'muse-colors)) 41 | 42 | (defgroup muse-ikiwiki nil 43 | "Options controlling the behavior of Muse integration with Ikiwiki." 44 | :group 'muse-publish) 45 | 46 | (defcustom muse-ikiwiki-header "" 47 | "Header used for publishing Ikiwiki output files. 48 | This may be text or a filename." 49 | :type 'string 50 | :group 'muse-ikiwiki) 51 | 52 | (defcustom muse-ikiwiki-footer "" 53 | "Footer used for publishing Ikiwiki output files. 54 | This may be text or a filename." 55 | :type 'string 56 | :group 'muse-ikiwiki) 57 | 58 | (defcustom muse-ikiwiki-markup-regexps 59 | `(;; Ikiwiki directives 60 | (1350 ,(concat "\\(\\\\?\\)\\[\\[!""\\(?:-\\|\\w\\)+" 61 | "\\([" muse-regexp-blank "\n]+" 62 | "\\(?:\\(?:\\(?:-\\|\\w\\)+=\\)?" 63 | "\\(?:\"\"\".*?\"\"\"\\|\"[^\"]+\"" 64 | "\\|[^]" muse-regexp-blank "\n]+\\)" 65 | "[" muse-regexp-blank "\n]*\\)*\\)?\\]\\]") 66 | 0 muse-ikiwiki-markup-directive)) 67 | "List of markup rules for publishing Ikiwiki markup on Muse pages. 68 | For more on the structure of this list, see `muse-publish-markup-regexps'." 69 | :type '(repeat (choice 70 | (list :tag "Markup rule" 71 | integer 72 | (choice regexp symbol) 73 | integer 74 | (choice string function symbol)) 75 | function)) 76 | :group 'muse-ikiwiki) 77 | 78 | ;;; Publishing 79 | 80 | (defun muse-ikiwiki-markup-directive () 81 | "Handle publishing of an Ikiwiki directive." 82 | (unless (get-text-property (match-beginning 0) 'read-only) 83 | (add-text-properties (match-beginning 0) (match-end 0) 84 | '(muse-no-paragraph t)) 85 | (muse-publish-mark-read-only (match-beginning 0) (match-end 0)))) 86 | 87 | (defun muse-ikiwiki-publish-buffer (name title &optional style) 88 | "Publish a buffer for Ikiwki. 89 | The name of the corresponding file is NAME. 90 | The name of the style is given by STYLE. It defaults to \"ikiwiki\"." 91 | (unless style (setq style "ikiwiki")) 92 | (unless title (setq title (muse-page-name name))) 93 | (let ((muse-batch-publishing-p t) 94 | (muse-publishing-current-file name) 95 | (muse-publishing-current-output-path name) 96 | (muse-publishing-current-style style) 97 | (font-lock-verbose nil) 98 | (vc-handled-backends nil)) ; don't activate VC when publishing files 99 | (run-hooks 'muse-before-publish-hook) 100 | (let ((muse-inhibit-before-publish-hook t)) 101 | (muse-publish-markup-buffer title style)))) 102 | 103 | (defun muse-ikiwiki-publish-file (file name &optional style) 104 | "Publish a single file for Ikiwiki. 105 | The name of the real file is NAME, and the name of the temporary 106 | file containing the content is FILE. 107 | The name of the style is given by STYLE. It defaults to \"ikiwiki\"." 108 | (if (not (stringp file)) 109 | (message "Error: No file given to publish") 110 | (unless style 111 | (setq style "ikiwiki")) 112 | (let ((output-path file) 113 | (target file) 114 | (vc-handled-backends nil) ; don't activate VC when publishing files 115 | auto-mode-alist 116 | muse-current-output-style) 117 | (setq auto-mode-alist 118 | (delete (cons (concat "\\." muse-file-extension "\\'") 119 | 'muse-mode-choose-mode) 120 | auto-mode-alist)) 121 | (setq muse-current-output-style (list :base style :path file)) 122 | (muse-with-temp-buffer 123 | (muse-insert-file-contents file) 124 | (muse-ikiwiki-publish-buffer name nil style) 125 | (when (muse-write-file output-path t) 126 | (muse-style-run-hooks :final style file output-path target)))))) 127 | 128 | (defun muse-ikiwiki-start-server (port) 129 | "Start Muse IPC server, initializing with the client on PORT." 130 | (muse-ipc-start "foo" #'muse-ikiwiki-publish-buffer port)) 131 | 132 | ;;; Colors 133 | 134 | (defface muse-ikiwiki-directive 135 | '((((class color) (background light)) 136 | (:foreground "dark green")) 137 | (((class color) (background dark)) 138 | (:foreground "green"))) 139 | "Face for Ikiwiki directives." 140 | :group 'muse-ikiwiki) 141 | 142 | (defun muse-colors-ikiwiki-directive () 143 | "Color ikiwiki directives." 144 | (let ((start (match-beginning 0))) 145 | (unless (or (eq (get-text-property start 'invisible) 'muse) 146 | (get-text-property start 'muse-comment) 147 | (get-text-property start 'muse-directive)) 148 | ;; beginning of line or space or symbol 149 | (save-excursion 150 | (and 151 | (catch 'valid 152 | (while t 153 | (skip-chars-forward "^\"]" muse-colors-region-end) 154 | (cond ((eq (point) (point-max)) 155 | (throw 'valid nil)) 156 | ((> (point) muse-colors-region-end) 157 | (throw 'valid nil)) 158 | ((eq (char-after) ?\") 159 | (if (and (< (1+ (point)) muse-colors-region-end) 160 | (eq (char-after (1+ (point))) ?\")) 161 | (if (and (< (+ 2 (point)) muse-colors-region-end) 162 | (eq (char-after (+ 2 (point))) ?\")) 163 | ;; triple-quote 164 | (progn 165 | (forward-char 3) 166 | (or (and (looking-at "\"\"\"") 167 | (goto-char (match-end 0))) 168 | (re-search-forward 169 | "\"\"\"" muse-colors-region-end t) 170 | (throw 'valid nil))) 171 | ;; empty quotes (""), which are invalid 172 | (throw 'valid nil)) 173 | ;; quote with content 174 | (forward-char 1) 175 | (skip-chars-forward "^\"" muse-colors-region-end) 176 | (when (eq (char-after) ?\") 177 | (forward-char 1)))) 178 | ((eq (char-after) ?\]) 179 | (forward-char 1) 180 | (when (and (< (point) muse-colors-region-end) 181 | (eq (char-after (point)) ?\])) 182 | (forward-char 1) 183 | (throw 'valid t))) 184 | (t (throw 'valid nil))))) 185 | ;; found a valid directive 186 | (let ((end (point))) 187 | ;; remove flyspell overlays 188 | (when (fboundp 'flyspell-unhighlight-at) 189 | (let ((cur start)) 190 | (while (> end cur) 191 | (flyspell-unhighlight-at cur) 192 | (setq cur (1+ cur))))) 193 | (add-text-properties start end 194 | '(face muse-ikiwiki-directive 195 | muse-directive t muse-no-flyspell t)) 196 | (when (progn 197 | (goto-char start) 198 | (skip-chars-forward "^\n" end) 199 | (and (eq (char-after) ?\n) 200 | (not (= (point) end)))) 201 | (add-text-properties start end 202 | '(font-lock-multiline t))))))))) 203 | 204 | (defun muse-ikiwiki-insinuate-colors () 205 | (add-to-list 'muse-colors-markup 206 | '("\\[\\[!" ?\[ muse-colors-ikiwiki-directive) 207 | nil)) 208 | 209 | (eval-after-load "muse-colors" '(muse-ikiwiki-insinuate-colors)) 210 | 211 | ;; Styles 212 | (muse-derive-style "ikiwiki" "xhtml" 213 | :header 'muse-ikiwiki-header 214 | :footer 'muse-ikiwiki-footer 215 | :regexps 'muse-ikiwiki-markup-regexps) 216 | 217 | (provide 'muse-ikiwiki) 218 | 219 | ;;; muse-ikiwiki.el ends here 220 | -------------------------------------------------------------------------------- /experimental/muse-message.el: -------------------------------------------------------------------------------- 1 | ;;; muse-message.el --- publish a file as an email message 2 | 3 | ;; Copyright (C) 2004, 2005 Free Software Foundation, Inc. 4 | 5 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 6 | 7 | ;; Emacs Muse is free software; you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published 9 | ;; by the Free Software Foundation; either version 3, or (at your 10 | ;; option) any later version. 11 | 12 | ;; Emacs Muse is distributed in the hope that it will be useful, but 13 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | ;; General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 19 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 | ;; Boston, MA 02110-1301, USA. 21 | 22 | ;;; Commentary: 23 | 24 | ;; This file is in experimental status due to unimplemented features. 25 | ;; 26 | ;; To make use of this file, put (require 'muse-message) in your .emacs. 27 | ;; 28 | ;; By default, the way to mark up an email message is to do the 29 | ;; following. 30 | ;; 31 | ;; - Enter Message mode. This is usually done automatically when you 32 | ;; compose an email message using your Emacs mail client of choice. 33 | ;; 34 | ;; - Use standard Muse markup instead of plain text for your message. 35 | ;; 36 | ;; - When you are ready to see what the email message will look like, 37 | ;; do `M-x muse-message-markup'. This will make two versions of 38 | ;; your message: plaintext and HTML. 39 | ;; 40 | ;; - If you want to do further editing, simply undo your changes, 41 | ;; edit some more, and run `muse-message-markup' when you're ready 42 | ;; to send. 43 | ;; 44 | ;; - Send the message. 45 | ;; 46 | ;; If you wish the markup to be automatic at the time of sending you 47 | ;; message (a risky proposition), just add `muse-message-markup' to 48 | ;; `message-send-hook'. 49 | 50 | ;;; Contributors: 51 | 52 | ;;; Code: 53 | 54 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 55 | ;; 56 | ;; Muse E-Mail Publishing (via alternative/html) 57 | ;; 58 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 59 | 60 | (require 'message) 61 | (require 'footnote) 62 | 63 | (require 'muse-publish) 64 | (require 'muse-html) 65 | 66 | (defgroup muse-message nil 67 | "Options controlling the behavior of Emacs Wiki Mail Markup." 68 | :group 'hypermedia 69 | :group 'muse-publish) 70 | 71 | (defcustom muse-message-publishing-style "message" 72 | "Style used for publishing the alternative/text section of a message." 73 | :type 'string 74 | :group 'muse-message) 75 | 76 | (defcustom muse-message-html-publishing-style "message-html" 77 | "Style used for publishing the alternative/html section of a message." 78 | :type 'string 79 | :group 'muse-message) 80 | 81 | (defcustom muse-message-indent " " 82 | "String used to pad indentend text." 83 | :type 'string 84 | :group 'muse-message) 85 | 86 | (defcustom muse-message-style-sheet 87 | "body { 88 | background: white; color: black; 89 | margin-left: 3%; margin-right: 7%; 90 | } 91 | 92 | p { margin-top: 1% } 93 | p.verse { margin-left: 3% } 94 | 95 | .example { margin-left: 3% } 96 | 97 | h2 { 98 | margin-top: 25px; 99 | margin-bottom: 0px; 100 | } 101 | h3 { margin-bottom: 0px; }" 102 | "Text to prepend to a Muse mail message being published. 103 | This text may contain markup tags." 104 | :type 'string 105 | :group 'muse-message) 106 | 107 | (defcustom muse-message-html-header 108 | " 109 | 110 | 111 | <lisp>(muse-publishing-directive \"title\")</lisp> 112 | 113 | user-mail-address\"> 114 | 117 | 118 | 119 | \n" 120 | "Text to prepend to a Muse mail message being published. 121 | This text may contain markup tags." 122 | :type 'string 123 | :group 'muse-message) 124 | 125 | (defcustom muse-message-html-footer 126 | "\n 127 | 128 | \n" 129 | "Text to append to a Muse mail message being published. 130 | This text may contain markup tags." 131 | :type 'string 132 | :group 'muse-message) 133 | 134 | (defcustom muse-message-markup-functions 135 | '((link . muse-message-markup-link)) 136 | "An alist of style types to custom functions for that kind of text. 137 | For more on the structure of this list, see 138 | `muse-publish-markup-functions'." 139 | :type '(alist :key-type symbol :value-type function) 140 | :group 'muse-message) 141 | 142 | (defcustom muse-message-markup-strings 143 | '((rule . " * * * *") 144 | (begin-verse . " ") 145 | (end-verse-line . "\n ") 146 | (verse-space . " ") 147 | (end-verse . "") 148 | (begin-underline . "_") 149 | (end-underline . "_") 150 | (begin-literal . "`") 151 | (end-literal . "'") 152 | (begin-emph . "/") 153 | (end-emph . "/") 154 | (begin-more-emph . "*") 155 | (end-more-emph . "*") 156 | (begin-most-emph . "*/") 157 | (end-most-emph . "/*")) 158 | "Strings used for marking up message text." 159 | :type '(alist :key-type symbol :value-type string) 160 | :group 'muse-message) 161 | 162 | (defcustom muse-message-markup-tags 163 | '(("example" t nil muse-message-example-tag) 164 | ("contents" nil t muse-message-contents-tag)) 165 | "A list of tag specifications, for specially marking up text. 166 | See the documentation for `muse-publish-markup-tags'." 167 | :type '(repeat (list (string :tag "Markup tag") 168 | (boolean :tag "Expect closing tag" :value t) 169 | (boolean :tag "Parse attributes" :value nil) 170 | function)) 171 | :group 'muse-message) 172 | 173 | (defcustom muse-message-markup-specials nil 174 | "A table of characters which must be represented specially." 175 | :type '(alist :key-type character :value-type string) 176 | :group 'muse-message) 177 | 178 | (defun muse-message-markup-link () 179 | (let ((desc (match-string 2)) 180 | (url (match-string 1))) 181 | (save-match-data 182 | (delete-region (match-beginning 0) (match-end 0)) 183 | (when desc (insert desc)) 184 | (save-excursion 185 | (Footnote-add-footnote) 186 | (insert url)) 187 | ""))) 188 | 189 | (defun muse-message-example-tag (beg end) 190 | "Mark up example and code by simply indenting them." 191 | (muse-publish-escape-specials beg end) 192 | (kill-line 1) 193 | (goto-char end) 194 | (kill-line -1) 195 | (string-rectangle beg (point) muse-message-indent) 196 | (muse-publish-mark-read-only beg (point))) 197 | 198 | ;; Copied from `muse-publish-contents-tag'. 199 | ;; FIXME: Make this do something worthwhile. 200 | (defun muse-message-contents-tag (beg end attrs) 201 | (set (make-local-variable 'muse-publish-generate-contents) 202 | (cons (copy-marker (point) t) 203 | (let ((depth (cdr (assoc "depth" attrs)))) 204 | (or (and depth (string-to-number depth)) 2))))) 205 | 206 | ;;;###autoload 207 | (defun muse-message-markup () 208 | "Markup a wiki-ish e-mail message as HTML alternative e-mail. 209 | This step is manual by default, to give the author a chance to review 210 | the results and ensure they are appropriate. 211 | If you wish it to be automatic (a risky proposition), just add this 212 | function to `message-send-hook'." 213 | (interactive) 214 | (save-excursion 215 | (message-goto-body) 216 | (let ((text (buffer-substring-no-properties (point) (point-max))) 217 | (subject (message-fetch-field "subject")) 218 | (encoding (muse-html-encoding))) 219 | (delete-region (point) (point-max)) 220 | (insert 221 | "<#multipart type=alternative>\n" 222 | "<#part type=text/plain charset=\"" encoding "\" nofile=yes>\n" 223 | (with-temp-buffer 224 | (insert text) 225 | (muse-publish-markup-buffer 226 | subject muse-message-publishing-style) 227 | (buffer-substring-no-properties (point-min) (point-max))) 228 | "\n<#part type=text/html charset=\"" encoding "\" nofile=yes>\n" 229 | (with-temp-buffer 230 | (insert text) 231 | (muse-publish-markup-buffer 232 | subject muse-message-html-publishing-style) 233 | (buffer-substring-no-properties (point-min) (point-max))) 234 | "<#/multipart>\n")))) 235 | 236 | (muse-define-style "message" 237 | :functions 'muse-message-markup-functions 238 | :strings 'muse-message-markup-strings 239 | :tags 'muse-message-markup-tags) 240 | 241 | (muse-derive-style "message-html" "html" 242 | :header 'muse-message-html-header 243 | :footer 'muse-message-html-footer) 244 | 245 | (muse-derive-style "message-xhtml" "xhtml" 246 | :header 'muse-message-html-header 247 | :footer 'muse-message-html-footer) 248 | 249 | (provide 'muse-message) 250 | 251 | ;;; muse-message.el ends here 252 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | -*- Text -*- 2 | This is the README file for Emacs Muse. 3 | 4 | The terms "Emacs Muse", "Emacs-Muse", and "Muse" are used 5 | interchangeably throughout this document to refer to this software. 6 | 7 | Synopsis 8 | ======== 9 | 10 | Emacs Muse is an authoring and publishing environment for Emacs. It 11 | simplifies the process of writings documents and publishing them to 12 | various output formats. 13 | 14 | Emacs Muse consists of two main parts: an enhanced text-mode for 15 | authoring documents and navigating within Muse projects, and a set of 16 | publishing styles for generating different kinds of output. 17 | 18 | Directory contents 19 | ================== 20 | 21 | The directory structure is as follows. 22 | 23 | etc :: Miscellaneous files like the emacs-wiki migration guide, the 24 | list of ideas for the future, and a RelaxNG schema for Muse XML. 25 | 26 | contrib :: Files that are not a part of Muse proper, but are useful 27 | enough to be bundled with Muse. 28 | 29 | examples :: Example configuration files for use with Muse, a 30 | publishable quickstart guide, and miscellaneous helper stuff. 31 | 32 | experimental :: Source code that is not yet considered stable. 33 | 34 | lisp :: Muse source code. 35 | 36 | scripts :: Scripts that are used when compiling Muse and publishing 37 | the QuickStart document; they might prove useful if you want to 38 | automate the building of Muse documents. 39 | 40 | texi :: The manual (muse.texi) and any supplemental sections. 41 | 42 | Getting started 43 | =============== 44 | 45 | Prerequisites 46 | ------------- 47 | 48 | You need either Emacs (21.1 or greater), XEmacs (21.4 or greater), or 49 | SXEmacs (warning: Muse has not been tested with SXEmacs). The current 50 | maintainer recommends using Emacs. 51 | 52 | Compilation 53 | ----------- 54 | 55 | This is an optional step, since Emacs Lisp source code does not 56 | necessarily have to be byte-compiled. It may yield a slight speed 57 | increase, however. 58 | 59 | A working copy of Emacs or XEmacs is needed in order to compile the 60 | Emacs Muse. By default, the program that is installed with the name 61 | `emacs' will be used. 62 | 63 | If you want to use the `xemacs' binary to perform the compilation, you 64 | must copy `Makefile.defs.default' to `Makefile.defs' in the top-level 65 | directory, and then edit `Makefile.defs' as follows. You can put 66 | either a full path to an Emacs or XEmacs binary or just the command 67 | name, as long as it is in the PATH. 68 | 69 | EMACS = xemacs 70 | SITEFLAG = -no-site-file 71 | # Edit the section as necessary 72 | install_info = install-info --section "XEmacs 21.4" $(1).info \ 73 | $(INFODIR)/dir || : 74 | 75 | Running `make' in the top-level directory should compile the Muse 76 | source files in the `lisp' directory, and generate an autoloads 77 | file in `lisp/muse-autoloads.el'. 78 | 79 | Installation 80 | ------------ 81 | 82 | Muse may be installed into your file hierarchy by doing the following. 83 | 84 | Copy `Makefile.defs.default' to `Makefile.defs' in the top-level 85 | directory, if you haven't done so already. Then edit the 86 | `Makefile.defs' file so that ELISPDIR points to where you want the 87 | source and compiled Muse files to be installed and INFODIR indicates 88 | where to put the Muse manual. You may use a combination of DESTDIR 89 | and PREFIX to further determine where the installed files should be 90 | placed. As mentioned earlier, you will want to edit EMACS and 91 | SITEFLAG as shown in the Compilation section if you are using XEmacs. 92 | 93 | If you are installing Muse on a Debian or Ubuntu system, you might 94 | want to change the value of INSTALLINFO as specified in 95 | `Makefile.defs'. 96 | 97 | If you wish to install Muse to different locations than the defaults 98 | specify, edit `Makefile.defs' accordingly. 99 | 100 | Run `make' as a normal user, if you haven't done so already. 101 | 102 | Run `make install' as the root user if you have chosen installation 103 | locations that require this. 104 | 105 | Insinuation 106 | ----------- 107 | 108 | Two things need to happen in order for Muse to be usable with your 109 | version of Emacs or XEmacs. 110 | 111 | 1. The location of the Muse directory needs to be added to the load 112 | path so that your variant of Emacs can find it. 113 | 114 | 2. You need to load whichever Muse files you wish to make use of. 115 | 116 | A quick example that accomplishes both of these follows. 117 | 118 | ;; Add this to your .emacs or .xemacs/init.el file. 119 | (setq load-path (add-to-list 'load-path "/path/to/muse")) 120 | (require 'muse-mode) 121 | (require 'muse-publish) 122 | (require 'muse-html) ;; and so on 123 | 124 | Documentation 125 | ------------- 126 | 127 | The Muse manual may be generated by running `make doc'. 128 | 129 | It will produce two files: an Info file called `muse.info' and an HTML 130 | document called `muse.html'. Both of these will be created in the 131 | `texi' directory. 132 | 133 | This manual is also available online in several forms. 134 | 135 | - PDF: http://mwolson.org/static/doc/muse.pdf 136 | - HTML (single file): http://mwolson.org/static/doc/muse.html 137 | - HTML (multiple files): http://mwolson.org/static/doc/muse/ 138 | 139 | QuickStart 140 | ---------- 141 | 142 | Type "make examples" to generate a quickstart guide for Muse. An HTML 143 | document called QuickStart.html, an Info document called 144 | QuickStart.info, and a PDF file called QuickStart.pdf will be created 145 | in the `examples' directory. 146 | 147 | If you do not have a working LaTeX installation with the proper fonts, 148 | the PDF file will not be successfully generated. 149 | 150 | To see the document that is interpreted in order to generate these 151 | files, take a look at `examples/QuickStart.muse'. 152 | 153 | To view the generated Info document from within Emacs, try the 154 | following. 155 | 156 | C-u M-x info RET /path/to/muse/examples/QuickStart.info RET 157 | 158 | Further Documentation 159 | ===================== 160 | 161 | Please consult http://www.emacswiki.org/cgi-bin/wiki/EmacsMuse to find 162 | more information on bugs, unimplemented features, and user-contributed 163 | tweaks. 164 | 165 | The current maintainer's webpage for Muse is at 166 | http://mwolson.org/projects/EmacsMuse.html. 167 | 168 | If you wish to participate in the development of Muse, or track the 169 | latest development changes, please read the `Development' section of 170 | the Muse manual (in the `Obtaining Muse' chapter) for instructions. 171 | 172 | Mailing Lists 173 | ============= 174 | 175 | Mailing lists for Muse exist. 176 | 177 | muse-el-announce :: 178 | Low-traffic list for Muse-related announcements. 179 | 180 | You can join this mailing list (muse-el-announce@gna.org) 181 | using the subscription form at 182 | http://mail.gna.org/listinfo/muse-el-announce/. 183 | 184 | This mailing list is also available via Gmane (http://gmane.org/). 185 | The group is called 186 | gmane.emacs.muse.announce. 187 | 188 | muse-el-discuss :: 189 | Discussion, bugfixes, suggestions, tips, and the like for Muse. 190 | This mailing list also includes the content of muse-el-announce. 191 | 192 | You can join this mailing list (muse-el-discuss@gna.org) 193 | using the subscription form at 194 | http://mail.gna.org/listinfo/muse-el-discuss/. 195 | 196 | This mailing list is also available via Gmane with the identifier 197 | gmane.emacs.muse.general. 198 | 199 | muse-el-logs :: 200 | Log messages for commits made to Muse. 201 | 202 | You can join this mailing list (muse-el-logs@gna.org) using 203 | the subscription form at 204 | http://mail.gna.org/listinfo/muse-el-logs/. 205 | 206 | This mailing list is also available via Gmane with the identifier 207 | gmane.emacs.muse.scm. 208 | 209 | muse-el-commits :: 210 | Generated bug reports for Emacs Muse. If you use our bug-tracker at 211 | https://gna.org/bugs/?group=muse-el, the bug reports will be sent to 212 | this list automatically. 213 | 214 | You can join this mailing list (muse-el-commits@gna.org) using 215 | the subscription form at 216 | http://mail.gna.org/listinfo/muse-el-commits/. 217 | 218 | This mailing list is also available via Gmane with the identifier 219 | gmane.emacs.muse.cvs. 220 | 221 | License 222 | ======= 223 | 224 | Emacs Muse is free software; you can redistribute it and/or modify it 225 | under the terms of the GNU General Public License as published by the 226 | Free Software Foundation; either version 3, or (at your option) any 227 | later version. 228 | 229 | Emacs Muse is distributed in the hope that it will be useful, but 230 | WITHOUT ANY WARRANTY; without even the implied warranty of 231 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 232 | General Public License for more details. 233 | 234 | You should have received a copy of the GNU General Public License 235 | along with Emacs Muse; see the file COPYING. If not, write to the 236 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 237 | Boston, MA 02110-1301, USA. 238 | 239 | The Muse manual is available under the terms of the GNU Free 240 | Documentation License, Version 1.2 or any later version published by 241 | the Free Software Foundation; with no Invariant Sections, and with the 242 | Front-Cover texts and Back-Cover Texts as specified in the manual. A 243 | copy of the license is included in the section entitled "GNU Free 244 | Documentation License" in the Muse manual. All Emacs Lisp code 245 | contained in the manual may be used, distributed, and modified without 246 | restriction. 247 | 248 | The PNG images included in the examples/ directory may be used, 249 | distributed, and modified without restriction. 250 | 251 | The contents of the contrib/blosxom and contrib/pyblosxom directories 252 | are available under the terms of other licenses. Please consult the 253 | header of each file for the appropriate license text. 254 | -------------------------------------------------------------------------------- /etc/muse.rnc: -------------------------------------------------------------------------------- 1 | namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" 2 | namespace rng = "http://relaxng.org/ns/structure/1.0" 3 | 4 | # Emacs Muse RELAX NG Schema v. 1.2 5 | # Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 6 | # Free Software Foundation, Inc. 7 | 8 | # Author: Brad Collins (brad AT chenla DOT org) 9 | # Maintainer: Michael Olson 10 | 11 | # This is free software; you can redistribute it and/or modify it 12 | # under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 3 of the License, or 14 | # (at your option) any later version. This material is distributed in 15 | # the hope that it will be useful, but WITHOUT ANY WARRANTY; without 16 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 17 | # PARTICULAR PURPOSE. See the GNU General Public License for more 18 | # details.You should have received a copy of the GNU General Public 19 | # License along with this file; if not, write to the Free Software 20 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 21 | # 02111-1307, USA. 22 | 23 | # Commentary: 24 | # 25 | # RelaxNG Compact syntax can be converted into RelaxNG XML Syntax, 26 | # DTD format and XML Schema language using free tools. 27 | # 28 | # Emacs users are encouraged to use James Clarke's nxml-mode for 29 | # editing and validating XML files. If you are in nxml-mode use the 30 | # command C-c C-s C-f to point to this schema file, say yes if you 31 | # are asked if you want to copy the file to your location, and then 32 | # C-c C-s C-a can be used to reload the schema if you make changes 33 | # to the file. 34 | 35 | # History: 36 | # 37 | # Version 0.1: 38 | # - Original version by Brad Collins. 39 | # 40 | # Version 0.2: 41 | # - Hacked it to the point of working with Muse's QuickStart 42 | # document. 43 | # 44 | # Version 0.3: 45 | # - Permit lists to be nested. 46 | # 47 | # Version 1.0: 48 | # - Permit paragraph-level markup, such as links, to appear in 49 | # table lines. 50 | # - Support multiple definitions in a definition list. 51 | # - Permit a list to be nested inside of a definition. 52 | # - Permit a link to be inside of a title. 53 | # - Permit emphasis to be inside of other emphasis. 54 | # 55 | # Version 1.1: 56 | # - Add the tag. 57 | # 58 | # Version 1.2: 59 | # - Add the
tag. 60 | # - Don't allow tags inside of format elements. 61 | 62 | # Contributors: 63 | 64 | # Schema: 65 | 66 | start = MUSE 67 | 68 | ## root element 69 | MUSE = 70 | element MUSE { 71 | muse.element.pageinfo? 72 | & muse.element.section* 73 | & muse.element.p* 74 | & muse.element.blockquote* 75 | & muse.element.table* 76 | & muse.element.list* 77 | & muse.element.hr* 78 | & muse.element.image* 79 | & muse.element.example* 80 | & muse.element.verse* 81 | } 82 | 83 | # ------------------------------------------------ 84 | # Pageinfo elements 85 | # ------------------------------------------------ 86 | ## pageinfo element used for metadata 87 | ## for the page 88 | muse.element.pageinfo = element pageinfo { 89 | muse.element.title? 90 | & muse.element.author? 91 | & muse.element.maintainer? 92 | & muse.element.pubdate? }? 93 | 94 | ## page title element 95 | muse.element.title = element title { 96 | muse.element.link* 97 | & text }? 98 | 99 | ## page author element 100 | muse.element.author = element author { text }? 101 | 102 | ## page maintainer element 103 | muse.element.maintainer = element maintainer { text }? 104 | 105 | ## page publication date element 106 | muse.element.pubdate = element pubdate { text }? 107 | 108 | # ------------------------------------------------ 109 | # Block elements 110 | # ------------------------------------------------ 111 | 112 | muse.element.section = element section { 113 | muse.attribute.type? 114 | & muse.attribute.level? 115 | & muse.element.section* 116 | & muse.element.title* 117 | & muse.element.p* 118 | & muse.element.blockquote* 119 | & muse.element.table* 120 | & muse.element.list* 121 | & muse.element.hr* 122 | & muse.element.image* 123 | & muse.element.example* 124 | & muse.element.verse* 125 | & text }? 126 | 127 | ## blockquote element 128 | muse.element.blockquote = element blockquote { 129 | muse.element.title? 130 | & muse.element.p* }? 131 | 132 | ## paragraph element 133 | muse.element.p = element p { 134 | muse.element.br* 135 | & muse.element.code* 136 | & muse.element.cite* 137 | & muse.element.format* 138 | & muse.element.image* 139 | & muse.element.link* 140 | & muse.element.image* 141 | & muse.element.anchor* 142 | & muse.element.footnote* 143 | & text }? 144 | 145 | ## example element 146 | muse.element.example = element example { text }? 147 | 148 | ## verse element 149 | muse.element.verse = element verse { 150 | muse.element.line* }? 151 | 152 | ## verse line element 153 | muse.element.line = element line { 154 | muse.element.br* 155 | & muse.element.code* 156 | & muse.element.cite* 157 | & muse.element.format* 158 | & muse.element.image* 159 | & muse.element.link* 160 | & muse.element.image* 161 | & muse.element.anchor* 162 | & muse.element.footnote* 163 | & text }? 164 | 165 | # ------------------------------------------------ 166 | # Unordered list elements 167 | # ------------------------------------------------ 168 | 169 | muse.element.list = element list { 170 | muse.attribute.type? 171 | & muse.element.item* }? 172 | 173 | muse.element.item = element item { 174 | muse.element.term? 175 | & muse.element.definition* 176 | & muse.element.br* 177 | & muse.element.code* 178 | & muse.element.cite* 179 | & muse.element.format* 180 | & muse.element.image* 181 | & muse.element.link* 182 | & muse.element.p* 183 | & muse.element.blockquote* 184 | & muse.element.table* 185 | & muse.element.example* 186 | & muse.element.verse* 187 | & muse.element.list* 188 | & text }? 189 | 190 | # ------------------------------------------------ 191 | # Definition list elements 192 | # ------------------------------------------------ 193 | 194 | muse.element.term = element term { 195 | muse.element.br* 196 | & muse.element.code* 197 | & muse.element.cite* 198 | & muse.element.format* 199 | & muse.element.image* 200 | & muse.element.link* 201 | & muse.element.image* 202 | & text }? 203 | 204 | ## def 205 | muse.element.definition = element definition { 206 | muse.element.br* 207 | & muse.element.code* 208 | & muse.element.cite* 209 | & muse.element.format* 210 | & muse.element.image* 211 | & muse.element.link* 212 | & muse.element.image* 213 | & muse.element.list* 214 | & text }? 215 | 216 | # ------------------------------------------------ 217 | # Inline elements 218 | # ------------------------------------------------ 219 | 220 | ## format element 221 | ## used for emphasis, underlining, and centering paragraphs 222 | muse.element.format = element format { 223 | muse.attribute.type? 224 | & muse.attribute.level? 225 | & muse.element.code* 226 | & muse.element.format* 227 | & text }? 228 | 229 | ## cite element 230 | ## used for citing sources 231 | muse.element.cite = element cite { 232 | muse.attribute.type? 233 | & text }? 234 | 235 | ## code element 236 | ## used for small pieces of monospace text, like commands 237 | muse.element.code = element code { text }? 238 | 239 | muse.element.image = element image { muse.attribute.href? }? 240 | 241 | ## horizontal rule element 242 | muse.element.hr = element hr { empty }? 243 | 244 | ## footnote element 245 | muse.element.footnote = element footnote { text }? 246 | 247 | ## anchor element 248 | muse.element.anchor = element anchor { muse.attribute.id }? 249 | 250 | ## link element 251 | muse.element.link = element link { 252 | muse.attribute.type? 253 | & muse.attribute.href 254 | & text }? 255 | 256 | # ------------------------------------------------ 257 | # Attributes 258 | # ------------------------------------------------ 259 | 260 | ## type attribute 261 | muse.attribute.type = attribute type { text }? 262 | 263 | ## level attribute 264 | muse.attribute.level = attribute level { text }? 265 | 266 | ## href attribute -- must have valid URI 267 | muse.attribute.href = attribute href { xsd:anyURI }? 268 | 269 | ## id attribute 270 | muse.attribute.id = attribute id { text }? 271 | 272 | # ------------------------------------------------ 273 | # Table elements 274 | # ------------------------------------------------ 275 | 276 | ## table element 277 | muse.element.table = element table { 278 | muse.element.tbody* 279 | & muse.element.thead* 280 | & muse.element.tfoot* }? 281 | 282 | ## table body element 283 | muse.element.tbody = element tbody { muse.element.tr* }? 284 | 285 | ## table header element 286 | muse.element.thead = element thead { muse.element.tr* }? 287 | 288 | ## table footer element 289 | muse.element.tfoot = element tfoot { muse.element.tr* }? 290 | 291 | ## table row element 292 | muse.element.tr = element tr { 293 | muse.element.td* 294 | & muse.element.th* }? 295 | 296 | ## td element 297 | muse.element.td = element td { 298 | muse.element.br* 299 | & muse.element.code* 300 | & muse.element.cite* 301 | & muse.element.format* 302 | & muse.element.image* 303 | & muse.element.link* 304 | & muse.element.image* 305 | & muse.element.anchor* 306 | & muse.element.footnote* 307 | & text }? 308 | 309 | ## th element 310 | muse.element.th = element th { 311 | muse.element.br* 312 | & muse.element.code* 313 | & muse.element.cite* 314 | & muse.element.format* 315 | & muse.element.image* 316 | & muse.element.link* 317 | & muse.element.image* 318 | & muse.element.anchor* 319 | & muse.element.footnote* 320 | & text }? 321 | -------------------------------------------------------------------------------- /lisp/muse-protocols.el: -------------------------------------------------------------------------------- 1 | ;;; muse-protocols.el --- URL protocols that Muse recognizes 2 | 3 | ;; Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 4 | ;; Free Software Foundation, Inc. 5 | 6 | ;; Author: Brad Collins (brad AT chenla DOT org) 7 | 8 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 9 | 10 | ;; Emacs Muse is free software; you can redistribute it and/or modify 11 | ;; it under the terms of the GNU General Public License as published 12 | ;; by the Free Software Foundation; either version 3, or (at your 13 | ;; option) any later version. 14 | 15 | ;; Emacs Muse is distributed in the hope that it will be useful, but 16 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | ;; General Public License for more details. 19 | 20 | ;; You should have received a copy of the GNU General Public License 21 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 22 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 23 | ;; Boston, MA 02110-1301, USA. 24 | 25 | ;;; Commentary: 26 | 27 | ;; Here's an example for adding a protocol for the site yubnub, a Web 28 | ;; Command line service. 29 | ;; 30 | ;; (add-to-list 'muse-url-protocols '("yubnub://" muse-browse-url-yubnub 31 | ;; muse-resolve-url-yubnub)) 32 | ;; 33 | ;; (defun muse-resolve-url-yubnub (url) 34 | ;; "Resolve a yubnub URL." 35 | ;; ;; Remove the yubnub:// 36 | ;; (when (string-match "\\`yubnub://\\(.+\\)" url) 37 | ;; (match-string 1))) 38 | ;; 39 | ;; (defun muse-browse-url-yubnub (url) 40 | ;; "If this is a yubnub URL-command, jump to it." 41 | ;; (setq url (muse-resolve-url-yubnub url)) 42 | ;; (browse-url (concat "http://yubnub.org/parser/parse?command=" 43 | ;; url))) 44 | 45 | ;;; Contributors: 46 | 47 | ;; Phillip Lord (Phillip.Lord AT newcastle DOT ac DOT uk) provided a 48 | ;; handler for DOI URLs. 49 | 50 | ;; Stefan Schlee fixed a bug with handling of colons at the end of 51 | ;; URLs. 52 | 53 | ;; Valery V. Vorotyntsev contribued the woman:// protocol handler and 54 | ;; simplified `muse-browse-url-man'. 55 | 56 | ;;; Code: 57 | 58 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 59 | ;; 60 | ;; Muse URL Protocols 61 | ;; 62 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 63 | 64 | (require 'info) 65 | (require 'muse-regexps) 66 | 67 | (defvar muse-url-regexp nil 68 | "A regexp used to match URLs within a Muse page. 69 | This is autogenerated from `muse-url-protocols'.") 70 | 71 | (defun muse-update-url-regexp (sym value) 72 | (setq muse-url-regexp 73 | (concat "\\<\\(" (mapconcat 'car value "\\|") "\\)" 74 | "[^][" muse-regexp-blank "\"'()<>^`{}\n]*" 75 | "[^][" muse-regexp-blank "\"'()<>^`{}.,;:\n]+")) 76 | (set sym value)) 77 | 78 | (defcustom muse-url-protocols 79 | '(("[uU][rR][lL]:" muse-browse-url-url identity) 80 | ("info://" muse-browse-url-info nil) 81 | ("man://" muse-browse-url-man nil) 82 | ("woman://" muse-browse-url-woman nil) 83 | ("google://" muse-browse-url-google muse-resolve-url-google) 84 | ("http:/?/?" browse-url identity) 85 | ("https:/?/?" browse-url identity) 86 | ("ftp:/?/?" browse-url identity) 87 | ("gopher://" browse-url identity) 88 | ("telnet://" browse-url identity) 89 | ("wais://" browse-url identity) 90 | ("file://?" browse-url identity) 91 | ("dict:" muse-browse-url-dict muse-resolve-url-dict) 92 | ("doi:" muse-browse-url-doi muse-resolve-url-doi) 93 | ("news:" browse-url identity) 94 | ("snews:" browse-url identity) 95 | ("mailto:" browse-url identity)) 96 | "A list of (PROTOCOL BROWSE-FUN RESOLVE-FUN) used to match URL protocols. 97 | PROTOCOL describes the first part of the URL, including the 98 | \"://\" part. This may be a regexp. 99 | 100 | BROWSE-FUN should accept URL as an argument and open the URL in 101 | the current window. 102 | 103 | RESOLVE-FUN should accept URL as an argument and return the final 104 | URL, or nil if no URL should be included." 105 | :type '(repeat (list :tag "Protocol" 106 | (string :tag "Regexp") 107 | (function :tag "Browse") 108 | (choice (function :tag "Resolve") 109 | (const :tag "Don't resolve" nil)))) 110 | :set 'muse-update-url-regexp 111 | :group 'muse) 112 | 113 | (add-hook 'muse-update-values-hook 114 | (lambda () 115 | (muse-update-url-regexp 'muse-url-protocols muse-url-protocols))) 116 | 117 | (defcustom muse-wikipedia-country "en" 118 | "Indicate the 2-digit country code that we use for Wikipedia 119 | queries." 120 | :type 'string 121 | :options '("de" "en" "es" "fr" "it" "pl" "pt" "ja" "nl" "sv") 122 | :group 'muse) 123 | 124 | (defun muse-protocol-find (proto list) 125 | "Return the first element of LIST whose car matches the regexp PROTO." 126 | (catch 'found 127 | (dolist (item list) 128 | (when (string-match (concat "\\`" (car item)) proto) 129 | (throw 'found item))))) 130 | 131 | ;;;###autoload 132 | (defun muse-browse-url (url &optional other-window) 133 | "Handle URL with the function specified in `muse-url-protocols'. 134 | If OTHER-WINDOW is non-nil, open in a different window." 135 | (interactive (list (read-string "URL: ") 136 | current-prefix-arg)) 137 | ;; Strip text properties 138 | (when (fboundp 'set-text-properties) 139 | (set-text-properties 0 (length url) nil url)) 140 | (when other-window 141 | (switch-to-buffer-other-window (current-buffer))) 142 | (when (string-match muse-url-regexp url) 143 | (let* ((proto (match-string 1 url)) 144 | (entry (muse-protocol-find proto muse-url-protocols))) 145 | (when entry 146 | (funcall (cadr entry) url))))) 147 | 148 | (defun muse-resolve-url (url &rest ignored) 149 | "Resolve URL with the function specified in `muse-url-protocols'." 150 | (when (string-match muse-url-regexp url) 151 | (let* ((proto (match-string 1 url)) 152 | (entry (muse-protocol-find proto muse-url-protocols))) 153 | (when entry 154 | (let ((func (car (cddr entry)))) 155 | (if func 156 | (setq url (funcall func url)) 157 | (setq url nil)))))) 158 | url) 159 | 160 | (defun muse-protocol-add (protocol browse-function resolve-function) 161 | "Add PROTOCOL to `muse-url-protocols'. PROTOCOL may be a regexp. 162 | 163 | BROWSE-FUNCTION should be a function that visits a URL in the 164 | current buffer. 165 | 166 | RESOLVE-FUNCTION should be a function that transforms a URL for 167 | publishing or returns nil if not linked." 168 | (add-to-list 'muse-url-protocols 169 | (list protocol browse-function resolve-function)) 170 | (muse-update-url-regexp 'muse-url-protocols 171 | muse-url-protocols)) 172 | 173 | (defun muse-browse-url-url (url) 174 | "Call `muse-protocol-browse-url' to browse URL. 175 | This is used when we are given something like 176 | \"URL:http://example.org/\". 177 | 178 | If you're looking for a good example for how to make a custom URL 179 | handler, look at `muse-browse-url-dict' instead." 180 | (when (string-match "\\`[uU][rR][lL]:\\(.+\\)" url) 181 | (muse-browse-url (match-string 1 url)))) 182 | 183 | (defun muse-resolve-url-dict (url) 184 | "Return the Wikipedia link corresponding with the given URL." 185 | (when (string-match "\\`dict:\\(.+\\)" url) 186 | (concat "http://" muse-wikipedia-country ".wikipedia.org/" 187 | "wiki/Special:Search?search=" (match-string 1 url)))) 188 | 189 | (defun muse-browse-url-dict (url) 190 | "If this is a Wikipedia URL, browse it." 191 | (let ((dict-url (muse-resolve-url-dict url))) 192 | (when dict-url 193 | (browse-url dict-url)))) 194 | 195 | (defun muse-resolve-url-doi (url) 196 | "Return the URL through DOI proxy server." 197 | (when (string-match "\\`doi:\\(.+\\)" url) 198 | (concat "http://dx.doi.org/" 199 | (match-string 1 url)))) 200 | 201 | (defun muse-browse-url-doi (url) 202 | "If this is a DOI URL, browse it. 203 | 204 | DOI's (digitial object identifiers) are a standard identifier 205 | used in the publishing industry." 206 | (let ((doi-url (muse-resolve-url-doi url))) 207 | (when doi-url 208 | (browse-url doi-url)))) 209 | 210 | (defun muse-resolve-url-google (url) 211 | "Return the correct Google search string." 212 | (when (string-match "\\`google:/?/?\\(.+\\)" url) 213 | (concat "http://www.google.com/search?q=" 214 | (match-string 1 url)))) 215 | 216 | (defun muse-browse-url-google (url) 217 | "If this is a Google URL, jump to it." 218 | (let ((google-url (muse-resolve-url-google url))) 219 | (when google-url 220 | (browse-url google-url)))) 221 | 222 | (defun muse-browse-url-info (url) 223 | "If this in an Info URL, jump to it." 224 | (require 'info) 225 | (cond 226 | ((string-match "\\`info://\\([^#\n]+\\)#\\(.+\\)" url) 227 | (Info-find-node (match-string 1 url) 228 | (match-string 2 url))) 229 | ((string-match "\\`info://\\([^#\n]+\\)" url) 230 | (Info-find-node (match-string 1 url) 231 | "Top")) 232 | ((string-match "\\`info://(\\([^)\n]+\\))\\(.+\\)" url) 233 | (Info-find-node (match-string 1 url) (match-string 2 url))) 234 | ((string-match "\\`info://\\(.+\\)" url) 235 | (Info-find-node (match-string 1 url) "Top")))) 236 | 237 | (defun muse-browse-url-man (url) 238 | "If this in a manpage URL, jump to it." 239 | (require 'man) 240 | (when (string-match "\\`man://\\([^(]+\\(([^)]+)\\)?\\)" url) 241 | (man (match-string 1 url)))) 242 | 243 | (defun muse-browse-url-woman (url) 244 | "If this is a WoMan URL, jump to it." 245 | (require 'woman) 246 | (when (string-match "\\`woman://\\(.+\\)" url) 247 | (woman (match-string 1 url)))) 248 | 249 | (provide 'muse-protocols) 250 | 251 | ;;; muse-protocols.el ends here 252 | -------------------------------------------------------------------------------- /lisp/muse-http.el: -------------------------------------------------------------------------------- 1 | ;;; muse-http.el --- publish HTML files over HTTP 2 | 3 | ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 4 | ;; Free Software Foundation, Inc. 5 | 6 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 7 | 8 | ;; Emacs Muse is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published 10 | ;; by the Free Software Foundation; either version 3, or (at your 11 | ;; option) any later version. 12 | 13 | ;; Emacs Muse is distributed in the hope that it will be useful, but 14 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | ;; General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 20 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 | ;; Boston, MA 02110-1301, USA. 22 | 23 | ;;; Commentary: 24 | 25 | ;;; Contributors: 26 | 27 | ;;; Code: 28 | 29 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 30 | ;; 31 | ;; Publishing HTML over HTTP (using httpd.el) 32 | ;; 33 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 34 | 35 | (require 'muse-html) 36 | (require 'muse-project) 37 | (require 'httpd) 38 | (require 'cgi) 39 | 40 | (defgroup muse-http nil 41 | "Options controlling the behavior of Emacs Muse over HTTP." 42 | :group 'press) 43 | 44 | (defcustom muse-http-maintainer (concat "webmaster@" (system-name)) 45 | "The maintainer address to use for the HTTP 'From' field." 46 | :type 'string 47 | :group 'muse-http) 48 | 49 | (defcustom muse-http-publishing-style "html" 50 | "The style to use when publishing projects over http." 51 | :type 'string 52 | :group 'muse-http) 53 | 54 | (defcustom muse-http-max-cache-size 64 55 | "The number of pages to cache when serving over HTTP. 56 | This only applies if set while running the persisted invocation 57 | server. See main documentation for the `muse-http' 58 | customization group." 59 | :type 'integer 60 | :group 'muse-http) 61 | 62 | (defvar muse-buffer-mtime nil) 63 | (make-variable-buffer-local 'muse-buffer-mtime) 64 | 65 | (defun muse-sort-buffers (l r) 66 | (let ((l-mtime (with-current-buffer l muse-buffer-mtime)) 67 | (r-mtime (with-current-buffer r muse-buffer-mtime))) 68 | (cond 69 | ((and (null l-mtime) (null r-mtime)) l) 70 | ((null l-mtime) r) 71 | ((null r-mtime) l) 72 | (t (muse-time-less-p r-mtime l-mtime))))) 73 | 74 | (defun muse-winnow-list (entries &optional predicate) 75 | "Return only those ENTRIES for which PREDICATE returns non-nil." 76 | (let ((flist (list t))) 77 | (let ((entry entries)) 78 | (while entry 79 | (if (funcall predicate (car entry)) 80 | (nconc flist (list (car entry)))) 81 | (setq entry (cdr entry)))) 82 | (cdr flist))) 83 | 84 | (defun muse-http-prune-cache () 85 | "If the page cache has become too large, prune it." 86 | (let* ((buflist 87 | (sort (muse-winnow-list (buffer-list) 88 | (function 89 | (lambda (buf) 90 | (with-current-buffer buf 91 | muse-buffer-mtime)))) 92 | 'muse-sort-buffers)) 93 | (len (length buflist))) 94 | (while (> len muse-http-max-cache-size) 95 | (kill-buffer (car buflist)) 96 | (setq len (1- len))))) 97 | 98 | (defvar muse-http-serving-p nil) 99 | 100 | (defun muse-http-send-buffer (&optional modified code msg) 101 | "Markup and send the contents of the current buffer via HTTP." 102 | (httpd-send (or code 200) (or msg "OK") 103 | "Server: muse.el/" muse-version httpd-endl 104 | "Connection: close" httpd-endl 105 | "MIME-Version: 1.0" httpd-endl 106 | "Date: " (format-time-string "%a, %e %b %Y %T %Z") 107 | httpd-endl 108 | "From: " muse-http-maintainer httpd-endl) 109 | (when modified 110 | (httpd-send-data "Last-Modified: " 111 | (format-time-string "%a, %e %b %Y %T %Z" modified) 112 | httpd-endl)) 113 | (httpd-send-data "Content-Type: text/html; charset=iso-8859-1" httpd-endl 114 | "Content-Length: " (number-to-string (1- (point-max))) 115 | httpd-endl httpd-endl 116 | (buffer-string)) 117 | (httpd-send-eof)) 118 | 119 | (defun muse-http-reject (title msg &optional annotation) 120 | (muse-with-temp-buffer 121 | (insert msg ".\n") 122 | (if annotation 123 | (insert annotation "\n")) 124 | (muse-publish-markup-buffer title muse-http-publishing-style) 125 | (muse-http-send-buffer nil 404 msg))) 126 | 127 | (defun muse-http-prepare-url (target explicit) 128 | (save-match-data 129 | (unless (or (not explicit) 130 | (string-match muse-url-regexp target) 131 | (string-match muse-image-regexp target) 132 | (string-match muse-file-regexp target)) 133 | (setq target (concat "page?" target 134 | "&project=" muse-http-serving-p)))) 135 | (muse-publish-read-only target)) 136 | 137 | (defun muse-http-render-page (name) 138 | "Render the Muse page identified by NAME. 139 | When serving from a dedicated Emacs process (see the httpd-serve 140 | script), a maximum of `muse-http-max-cache-size' pages will be 141 | cached in memory to speed up serving time." 142 | (let ((file (muse-project-page-file name muse-http-serving-p)) 143 | (muse-publish-url-transforms 144 | (cons 'muse-http-prepare-url muse-publish-url-transforms)) 145 | (inhibit-read-only t)) 146 | (when file 147 | (with-current-buffer (get-buffer-create file) 148 | (let ((modified-time (nth 5 (file-attributes file))) 149 | (muse-publishing-current-file file) 150 | muse-publishing-current-style) 151 | (when (or (null muse-buffer-mtime) 152 | (muse-time-less-p muse-buffer-mtime modified-time)) 153 | (erase-buffer) 154 | (setq muse-buffer-mtime modified-time)) 155 | (goto-char (point-max)) 156 | (when (bobp) 157 | (muse-insert-file-contents file t) 158 | (let ((styles (cddr (muse-project muse-http-serving-p))) 159 | style) 160 | (while (and styles (null style)) 161 | (let ((include-regexp 162 | (muse-style-element :include (car styles))) 163 | (exclude-regexp 164 | (muse-style-element :exclude (car styles)))) 165 | (when (and (or (and (null include-regexp) 166 | (null exclude-regexp)) 167 | (if include-regexp 168 | (string-match include-regexp file) 169 | (not (string-match exclude-regexp file)))) 170 | (not (muse-project-private-p file))) 171 | (setq style (car styles)) 172 | (while (muse-style-element :base style) 173 | (setq style 174 | (muse-style (muse-style-element :base style)))) 175 | (if (string= (car style) muse-http-publishing-style) 176 | (setq style (car styles)) 177 | (setq style nil)))) 178 | (setq styles (cdr styles))) 179 | (muse-publish-markup-buffer 180 | name (or style muse-http-publishing-style)))) 181 | (set-buffer-modified-p nil) 182 | (muse-http-prune-cache) 183 | (current-buffer)))))) 184 | 185 | (defun muse-http-transmit-page (name) 186 | "Render the Muse page identified by NAME. 187 | When serving from a dedicated Emacs process (see the httpd-serve 188 | script), a maximum of `muse-http-max-cache-size' pages will be 189 | cached in memory to speed up serving time." 190 | (let ((inhibit-read-only t) 191 | (buffer (muse-http-render-page name))) 192 | (if buffer 193 | (with-current-buffer buffer 194 | (muse-http-send-buffer muse-buffer-mtime))))) 195 | 196 | (defvar httpd-vars nil) 197 | 198 | (defsubst httpd-var (var) 199 | "Return value of VAR as a URL variable. If VAR doesn't exist, nil." 200 | (cdr (assoc var httpd-vars))) 201 | 202 | (defsubst httpd-var-p (var) 203 | "Return non-nil if VAR was passed as a URL variable." 204 | (not (null (assoc var httpd-vars)))) 205 | 206 | (defun muse-http-serve (page &optional content) 207 | "Serve the given PAGE from this press server." 208 | ;; index.html is really a reference to the project home page 209 | (if (and muse-project-alist 210 | (string-match "\\`index.html?\\'" page)) 211 | (setq page (concat "page?" 212 | (muse-get-keyword :default 213 | (cadr (car muse-project-alist)))))) 214 | ;; handle the actual request 215 | (let ((vc-follow-symlinks t) 216 | (muse-publish-report-threshhold nil) 217 | muse-http-serving-p 218 | httpd-vars) 219 | (save-excursion 220 | ;; process any CGI variables, if cgi.el is available 221 | (if (string-match "\\`\\([^&]+\\)&" page) 222 | (setq httpd-vars (cgi-decode (substring page (match-end 0))) 223 | page (match-string 1 page))) 224 | (unless (setq muse-http-serving-p (httpd-var "project")) 225 | (let ((project (car muse-project-alist))) 226 | (setq muse-http-serving-p (car project)) 227 | (setq httpd-vars (cons (cons "project" (car project)) 228 | httpd-vars)))) 229 | (if (and muse-http-serving-p 230 | (string-match "\\`page\\?\\(.+\\)" page)) 231 | (muse-http-transmit-page (match-string 1 page)))))) 232 | 233 | (if (featurep 'httpd) 234 | (httpd-add-handler "\\`\\(index\\.html?\\|page\\(\\?\\|\\'\\)\\)" 235 | 'muse-http-serve)) 236 | 237 | (provide 'muse-http) 238 | 239 | ;;; muse-http.el ends here 240 | -------------------------------------------------------------------------------- /lisp/muse-regexps.el: -------------------------------------------------------------------------------- 1 | ;;; muse-regexps.el --- define regexps used by Muse 2 | 3 | ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 4 | ;; Free Software Foundation, Inc. 5 | 6 | ;; This file is part of Emacs Muse. It is not part of GNU Emacs. 7 | 8 | ;; Emacs Muse is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published 10 | ;; by the Free Software Foundation; either version 3, or (at your 11 | ;; option) any later version. 12 | 13 | ;; Emacs Muse is distributed in the hope that it will be useful, but 14 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | ;; General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with Emacs Muse; see the file COPYING. If not, write to the 20 | ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 | ;; Boston, MA 02110-1301, USA. 22 | 23 | ;;; Commentary: 24 | 25 | ;; This file is the part of the Muse project that describes regexps 26 | ;; that are used throughout the project. 27 | 28 | ;;; Contributors: 29 | 30 | ;;; Code: 31 | 32 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 33 | ;; 34 | ;; Muse Regular Expressions 35 | ;; 36 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 37 | 38 | (defgroup muse-regexp nil 39 | "Regular expressions used in publishing and syntax highlighting." 40 | :group 'muse) 41 | 42 | ;;; Deal with the lack of character classes for regexps in Emacs21 and 43 | ;;; XEmacs 44 | 45 | (defcustom muse-regexp-use-character-classes 'undecided 46 | "Indicate whether to use extended character classes like [:space:]. 47 | If 'undecided, Muse will use them if your emacs is known to support them. 48 | 49 | Emacs 22 and Emacs 21.3.50 are known to support them. XEmacs 50 | does not support them. 51 | 52 | Emacs 21.2 or higher support them, but with enough annoying edge 53 | cases that the sanest default is to leave them disabled." 54 | :type '(choice (const :tag "Yes" t) 55 | (const :tag "No" nil) 56 | (const :tag "Let Muse decide" undecided)) 57 | :group 'muse-regexp) 58 | 59 | (defvar muse-regexp-emacs-revision 60 | (save-match-data 61 | (and (string-match "^[0-9]+\\.[0-9]+\\.\\([0-9]+\\)" 62 | emacs-version) 63 | (match-string 1 emacs-version) 64 | (string-to-number (match-string 1 emacs-version)))) 65 | "The revision number of this version of Emacs.") 66 | 67 | (defun muse-extreg-usable-p () 68 | "Return non-nil if extended character classes can be used, 69 | nil otherwise. 70 | 71 | This is used when deciding the initial values of the muse-regexp 72 | options." 73 | (cond 74 | ((eq muse-regexp-use-character-classes t) 75 | t) 76 | ((eq muse-regexp-use-character-classes nil) 77 | nil) 78 | ((featurep 'xemacs) nil) ; unusable on XEmacs 79 | ((> emacs-major-version 21) t) ; usable if > 21 80 | ((< emacs-major-version 21) nil) 81 | ((< emacs-minor-version 3) nil) 82 | ;; don't use if version is of format 21.x 83 | ((null muse-regexp-emacs-revision) nil) 84 | ;; only trust 21.3.50 or higher 85 | ((>= muse-regexp-emacs-revision 50) t) 86 | (t nil))) 87 | 88 | (defcustom muse-regexp-blank 89 | (if (muse-extreg-usable-p) 90 | "[:blank:]" 91 | " \t") 92 | "Regexp to use in place of \"[:blank:]\". 93 | This should be something that matches spaces and tabs. 94 | 95 | It is like a regexp, but should be embeddable inside brackets. 96 | Muse will detect the appropriate value correctly most of 97 | the time." 98 | :type 'string 99 | :options '("[:blank:]" " \t") 100 | :group 'muse-regexp) 101 | 102 | (defcustom muse-regexp-alnum 103 | (if (muse-extreg-usable-p) 104 | "[:alnum:]" 105 | "A-Za-z0-9") 106 | "Regexp to use in place of \"[:alnum:]\". 107 | This should be something that matches all letters and numbers. 108 | 109 | It is like a regexp, but should be embeddable inside brackets. 110 | muse will detect the appropriate value correctly most of 111 | the time." 112 | :type 'string 113 | :options '("[:alnum:]" "A-Za-z0-9") 114 | :group 'muse-regexp) 115 | 116 | (defcustom muse-regexp-lower 117 | (if (muse-extreg-usable-p) 118 | "[:lower:]" 119 | "a-z") 120 | "Regexp to use in place of \"[:lower:]\". 121 | This should match all lowercase characters. 122 | 123 | It is like a regexp, but should be embeddable inside brackets. 124 | muse will detect the appropriate value correctly most of 125 | the time." 126 | :type 'string 127 | :options '("[:lower:]" "a-z") 128 | :group 'muse-regexp) 129 | 130 | (defcustom muse-regexp-upper 131 | (if (muse-extreg-usable-p) 132 | "[:upper:]" 133 | "A-Z") 134 | "Regexp to use in place of \"[:upper:]\". 135 | This should match all uppercase characters. 136 | 137 | It is like a regexp, but should be embeddable inside brackets. 138 | muse will detect the appropriate value correctly most of 139 | the time." 140 | :type 'string 141 | :options '("[:upper:]" "A-Z") 142 | :group 'muse-regexp) 143 | 144 | ;;; Regexps used to define Muse publishing syntax 145 | 146 | (defcustom muse-list-item-regexp 147 | (concat "^%s\\(\\([^\n" muse-regexp-blank "].*?\\)?::" 148 | "\\(?:[" muse-regexp-blank "]+\\|$\\)" 149 | "\\|[" muse-regexp-blank "]-[" muse-regexp-blank "]*" 150 | "\\|[" muse-regexp-blank "][0-9]+\\.[" muse-regexp-blank "]*\\)") 151 | "Regexp used to match the beginning of a list item. 152 | The '%s' will be replaced with a whitespace regexp when publishing." 153 | :type 'regexp 154 | :group 'muse-regexp) 155 | 156 | (defcustom muse-ol-item-regexp (concat "\\`[" muse-regexp-blank "]+[0-9]+\\.") 157 | "Regexp used to match an ordered list item." 158 | :type 'regexp 159 | :group 'muse-regexp) 160 | 161 | (defcustom muse-ul-item-regexp (concat "\\`[" muse-regexp-blank "]+-") 162 | "Regexp used to match an unordered list item." 163 | :type 'regexp 164 | :group 'muse-regexp) 165 | 166 | (defcustom muse-dl-term-regexp 167 | (concat "[" muse-regexp-blank "]*\\(.+?\\)[" 168 | muse-regexp-blank "]+::\\(?:[" muse-regexp-blank "]+\\|$\\)") 169 | "Regexp used to match a definition list term. 170 | The first match string must contain the term." 171 | :type 'regexp 172 | :group 'muse-regexp) 173 | 174 | (defcustom muse-dl-entry-regexp (concat "\\`[" muse-regexp-blank "]*::") 175 | "Regexp used to match a definition list entry." 176 | :type 'regexp 177 | :group 'muse-regexp) 178 | 179 | (defcustom muse-table-field-regexp 180 | (concat "[" muse-regexp-blank "]+\\(|+\\)\\(?:[" 181 | muse-regexp-blank "]\\|$\\)") 182 | "Regexp used to match table separators when publishing." 183 | :type 'regexp 184 | :group 'muse-regexp) 185 | 186 | (defcustom muse-table-line-regexp (concat ".*" muse-table-field-regexp ".*") 187 | "Regexp used to match a table line when publishing." 188 | :type 'regexp 189 | :group 'muse-regexp) 190 | 191 | (defcustom muse-table-hline-regexp (concat "[" muse-regexp-blank 192 | "]*|[-+]+|[" muse-regexp-blank 193 | "]*") 194 | "Regexp used to match a horizontal separator line in a table." 195 | :type 'regexp 196 | :group 'muse-regexp) 197 | 198 | (defcustom muse-table-el-border-regexp (concat "[" muse-regexp-blank "]*" 199 | "\\+\\(-*\\+\\)+" 200 | "[" muse-regexp-blank "]*") 201 | "Regexp used to match the beginning and end of a table.el-style table." 202 | :type 'regexp 203 | :group 'muse-regexp) 204 | 205 | (defcustom muse-table-el-line-regexp (concat "[" muse-regexp-blank "]*" 206 | "|\\(.*|\\)*" 207 | "[" muse-regexp-blank "]*") 208 | "Regexp used to match a table line of a table.el-style table." 209 | :type 'regexp 210 | :group 'muse-regexp) 211 | 212 | (defcustom muse-tag-regexp 213 | (concat "<\\([^/" muse-regexp-blank "\n][^" muse-regexp-blank 214 | "\n]*\\)\\(\\s-+[^<>]+[^\n]\\)?\\(/\\)?>") 215 | "A regexp used to find XML-style tags within a buffer when publishing. 216 | Group 1 should be the tag name, group 2 the properties, and group 217 | 3 the optional immediate ending slash." 218 | :type 'regexp 219 | :group 'muse-regexp) 220 | 221 | (defcustom muse-explicit-link-regexp 222 | "\\[\\[\\([^][\n]+\\)\\]\\(?:\\[\\([^][\n]+\\)\\]\\)?\\]" 223 | "Regexp used to match [[target][description]] links. 224 | Paren group 1 must match the URL, and paren group 2 the description." 225 | :type 'regexp 226 | :group 'muse-regexp) 227 | 228 | (defcustom muse-implicit-link-regexp 229 | (concat "\\([^" muse-regexp-blank "\n]+\\)") 230 | "Regexp used to match an implicit link. 231 | An implicit link is the largest block of text to be checked for 232 | URLs and bare WikiNames by the `muse-link-at-point' function. 233 | Paren group 1 is the text to be checked. 234 | 235 | URLs are checked by default. To get WikiNames, load 236 | muse-wiki.el. 237 | 238 | This is only used when you are using muse-mode.el, but not 239 | muse-colors.el. 240 | 241 | If the above applies, and you want to match things with spaces in 242 | them, you will have to modify this." 243 | :type 'regexp 244 | :group 'muse-regexp) 245 | 246 | ;;; Regexps used to determine file types 247 | 248 | (defcustom muse-file-regexp 249 | (concat "\\`[~/]\\|\\?\\|/\\'\\|\\." 250 | "\\(html?\\|pdf\\|mp3\\|el\\|zip\\|txt\\|tar\\)" 251 | "\\(\\.\\(gz\\|bz2\\)\\)?\\'") 252 | "A link matching this regexp will be regarded as a link to a file." 253 | :type 'regexp 254 | :group 'muse-regexp) 255 | 256 | (defcustom muse-image-regexp 257 | "\\.\\(eps\\|gif\\|jp\\(e?g\\)\\|p\\(bm\\|ng\\)\\|tiff\\|x\\([bp]m\\)\\)\\'" 258 | "A link matching this regexp will be published inline as an image. 259 | For example: 260 | 261 | [[./wife.jpg][A picture of my wife]] 262 | 263 | If you omit the description, the alt tag of the resulting HTML 264 | buffer will be the name of the file." 265 | :type 'regexp 266 | :group 'muse-regexp) 267 | 268 | (provide 'muse-regexps) 269 | 270 | ;;; muse-regexps.el ends here 271 | --------------------------------------------------------------------------------